summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2009-03-18 13:59:48 +0100
committerSumit Bose <sbose@redhat.com>2009-06-08 15:36:27 +0200
commit272d66315d6e8394dbcd5661103119a91a279108 (patch)
tree223321a92c5dcd6a5ef3293101c3d4e7418da826
parent7fc0bcafaf0b186d8dfa4f6a42ab30f33164475f (diff)
downloadsssd-272d66315d6e8394dbcd5661103119a91a279108.tar.gz
sssd-272d66315d6e8394dbcd5661103119a91a279108.tar.xz
sssd-272d66315d6e8394dbcd5661103119a91a279108.zip
added kerberos backend and kdc locator plugin
-rw-r--r--server/Makefile.am27
-rw-r--r--server/conf_macros.m414
-rw-r--r--server/configure.ac2
-rw-r--r--server/external/krb5.m411
-rw-r--r--server/krb5_plugin/sssd_krb5_locator_plugin.c129
-rw-r--r--server/providers/data_provider.h2
-rw-r--r--server/providers/dp_auth_util.c6
-rw-r--r--server/providers/krb5/krb5_auth.c544
-rw-r--r--server/responder/pam/pamsrv_cmd.c20
-rw-r--r--sss_client/pam_sss.c2
-rw-r--r--sssd.spec.in16
11 files changed, 770 insertions, 3 deletions
diff --git a/server/Makefile.am b/server/Makefile.am
index 00e7057e5..561eb19b3 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -2,6 +2,7 @@ topdir=.
sssdlibexecdir = $(libexecdir)/sssd
sssdlibdir = $(libdir)/sssd
ldblibdir = $(libdir)/ldb
+krb5plugindir = @krb5pluginpath@
sssdconfdir = $(sysconfdir)/sssd
dbusintrospectdir = $(datarootdir)/sssd/introspect
dbuspolicydir = $(sysconfdir)/dbus-1/system.d
@@ -65,11 +66,15 @@ endif
sssdlib_LTLIBRARIES = \
libsss_ldap.la \
+ libsss_krb5.la \
libsss_proxy.la
ldblib_LTLIBRARIES = \
memberof.la
+krb5plugin_LTLIBRARIES = \
+ sssd_krb5_locator_plugin.la
+
noinst_LTLIBRARIES = \
libsss_crypt.la
libsss_crypt_la_SOURCES = \
@@ -380,6 +385,19 @@ libsss_proxy_la_LDFLAGS = \
-version-info 1:0:0 \
-module
+libsss_krb5_la_SOURCES = \
+ providers/krb5/krb5_auth.c
+libsss_krb5_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(KRB5_CFLAGS)
+libsss_krb5_la_LIBADD = \
+ $(PAM_LIBS) \
+ $(KRB5_LIBS) \
+ libsss_crypt.la
+libsss_krb5_la_LDFLAGS = \
+ -version-info 1:0:0 \
+ -module
+
memberof_la_SOURCES = \
ldb_modules/memberof.c
memberof_la_CFLAGS = \
@@ -388,6 +406,15 @@ memberof_la_LDFLAGS = \
-avoid-version \
-module
+sssd_krb5_locator_plugin_la_SOURCES = \
+ krb5_plugin/sssd_krb5_locator_plugin.c
+sssd_krb5_locator_plugin_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(KRB5_CFLAGS)
+sssd_krb5_locator_plugin_la_LDFLAGS = \
+ -avoid-version \
+ -module
+
############
# MANPAGES #
############
diff --git a/server/conf_macros.m4 b/server/conf_macros.m4
index 7e230bbf9..d1e48a54b 100644
--- a/server/conf_macros.m4
+++ b/server/conf_macros.m4
@@ -132,7 +132,6 @@ AC_DEFUN([WITH_INIT_DIR],
AC_SUBST(initdir)
])
-
AC_DEFUN([WITH_SHADOW_UTILS_PATH],
[ AC_ARG_WITH([shadow-utils-path],
[AC_HELP_STRING([--with-shadow-utils-path=PATH],
@@ -177,3 +176,16 @@ AC_DEFUN([WITH_XML_CATALOG],
AC_SUBST([SGML_CATALOG_FILES])
])
+AC_DEFUN([WITH_KRB5_PLUGIN_PATH],
+ [ AC_ARG_WITH([krb5-plugin-path],
+ [AC_HELP_STRING([--with-krb5-plugin-path=PATH],
+ [Path to kerberos plugin store [/usr/lib/krb5/plugins/libkrb5]]
+ )
+ ]
+ )
+ krb5pluginpath="/usr/lib/krb5/plugins/libkrb5"
+ if test x"$with_krb5_plugin_path" != x; then
+ krb5pluginpath=$with_krb5_plugin_path
+ fi
+ AC_SUBST(krb5pluginpath)
+ ])
diff --git a/server/configure.ac b/server/configure.ac
index a1060c11f..13c5e8adf 100644
--- a/server/configure.ac
+++ b/server/configure.ac
@@ -49,6 +49,7 @@ WITH_INIT_DIR
WITH_SHADOW_UTILS_PATH
WITH_MANPAGES
WITH_XML_CATALOG
+WITH_KRB5_PLUGIN_PATH
m4_include([external/pkg.m4])
m4_include([external/libpopt.m4])
@@ -59,6 +60,7 @@ m4_include([external/libldb.m4])
m4_include([external/pam.m4])
m4_include([external/ldap.m4])
m4_include([external/libpcre.m4])
+m4_include([external/krb5.m4])
m4_include([util/signal.m4])
PKG_CHECK_MODULES([DBUS],[dbus-1])
diff --git a/server/external/krb5.m4 b/server/external/krb5.m4
new file mode 100644
index 000000000..c5852d5eb
--- /dev/null
+++ b/server/external/krb5.m4
@@ -0,0 +1,11 @@
+AC_SUBST(KRB5_CFLAGS)
+AC_SUBST(KRB5_LIBS)
+AC_PATH_PROG(KRB5_CONFIG, krb5-config)
+AC_MSG_CHECKING(for working krb5-config)
+if test -x "$KRB5_CONFIG"; then
+ KRB5_CFLAGS="`$KRB5_CONFIG --cflags`"
+ KRB5_LIBS="`$KRB5_CONFIG --libs`"
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no. Please install MIT kerberos devel package)
+fi
diff --git a/server/krb5_plugin/sssd_krb5_locator_plugin.c b/server/krb5_plugin/sssd_krb5_locator_plugin.c
new file mode 100644
index 000000000..eda796a0c
--- /dev/null
+++ b/server/krb5_plugin/sssd_krb5_locator_plugin.c
@@ -0,0 +1,129 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <krb5/locate_plugin.h>
+
+struct sssd_ctx {
+ char *sssd_realm;
+ char *sssd_kdc;
+};
+
+krb5_error_code sssd_krb5_locator_init(krb5_context context,
+ void **private_data)
+{
+ struct sssd_ctx *ctx;
+ char *dummy;
+
+ ctx = calloc(1,sizeof(struct sssd_ctx));
+ if (ctx == NULL) return ENOMEM;
+
+ dummy = getenv("SSSD_REALM");
+ if (dummy == NULL) goto failed;
+ ctx->sssd_realm = strdup(dummy);
+ if (ctx->sssd_realm == NULL) goto failed;
+
+ dummy = getenv("SSSD_KDC");
+ if (dummy == NULL) goto failed;
+ ctx->sssd_kdc = strdup(dummy);
+ if (ctx->sssd_kdc == NULL) goto failed;
+
+ *private_data = ctx;
+
+ return 0;
+failed:
+ if (ctx->sssd_realm != NULL) free(ctx->sssd_realm);
+ if (ctx->sssd_kdc != NULL) free(ctx->sssd_kdc);
+ free(ctx);
+
+ private_data = NULL;
+
+ return EINVAL;
+}
+
+void sssd_krb5_locator_close(void *private_data)
+{
+ struct sssd_ctx *ctx;
+
+ if (private_data == NULL) return;
+
+ ctx = (struct sssd_ctx *) private_data;
+ free(ctx->sssd_realm);
+ free(ctx->sssd_kdc);
+ free(ctx);
+
+ return;
+}
+
+krb5_error_code sssd_krb5_locator_lookup(void *private_data,
+ enum locate_service_type svc,
+ const char *realm,
+ int socktype,
+ int family,
+ int (*cbfunc)(void *, int, struct sockaddr *),
+ void *cbdata)
+{
+ int ret;
+ struct sockaddr_in addr;
+ struct sssd_ctx *ctx;
+
+ if (private_data == NULL) return KRB5_PLUGIN_NO_HANDLE;
+ ctx = (struct sssd_ctx *) private_data;
+
+#ifdef KRB5_PLUGIN_DEBUG
+ fprintf(stderr,"[%s][%s][%s][%d][%d][%d]\n", realm, ctx->sssd_realm,
+ ctx->sssd_kdc, socktype,
+ family, svc);
+#endif
+
+ switch (svc) {
+ case locate_service_kdc:
+ case locate_service_master_kdc:
+ case locate_service_kadmin:
+ break;
+ case locate_service_krb524:
+ case locate_service_kpasswd:
+ return KRB5_PLUGIN_NO_HANDLE;
+ default:
+ return EINVAL;
+ }
+
+ switch (family) {
+ case AF_UNSPEC:
+ case AF_INET:
+ break;
+ default:
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+
+ switch (socktype) {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ break;
+ default:
+ return EINVAL;
+ }
+
+ if (strcmp(realm, ctx->sssd_realm) != 0)
+ return KRB5_PLUGIN_NO_HANDLE;
+
+ addr.sin_family = AF_INET;
+ ret = inet_aton(ctx->sssd_kdc, &addr.sin_addr);
+ if (ret == 0) return EINVAL;
+ addr.sin_port = htons(88);
+
+ ret = cbfunc(cbdata, socktype, (struct sockaddr *) &addr);
+
+ return 0;
+}
+
+const krb5plugin_service_locate_ftable service_locator = {
+ 0, /* version */
+ sssd_krb5_locator_init,
+ sssd_krb5_locator_close,
+ sssd_krb5_locator_lookup,
+};
diff --git a/server/providers/data_provider.h b/server/providers/data_provider.h
index 95a1b379c..b747e69bd 100644
--- a/server/providers/data_provider.h
+++ b/server/providers/data_provider.h
@@ -117,6 +117,8 @@ struct pam_data {
bool offline_auth;
int priv;
+ uid_t pw_uid;
+ gid_t gr_gid;
};
void pam_print_data(int l, struct pam_data *pd);
diff --git a/server/providers/dp_auth_util.c b/server/providers/dp_auth_util.c
index 279e50b62..7219917d4 100644
--- a/server/providers/dp_auth_util.c
+++ b/server/providers/dp_auth_util.c
@@ -35,6 +35,8 @@ void pam_print_data(int l, struct pam_data *pd)
DEBUG(l, ("newauthtok type: %d\n", pd->newauthtok_type));
DEBUG(l, ("newauthtok size: %d\n", pd->newauthtok_size));
DEBUG(l, ("priv: %d\n", pd->priv));
+ DEBUG(l, ("pw_uid: %d\n", pd->pw_uid));
+ DEBUG(l, ("gr_gid: %d\n", pd->gr_gid));
}
int pam_add_response(struct pam_data *pd, enum response_type type,
@@ -83,6 +85,8 @@ bool dp_pack_pam_request(DBusMessage *msg, struct pam_data *pd)
&(pd->newauthtok),
pd->newauthtok_size,
DBUS_TYPE_INT32, &(pd->priv),
+ DBUS_TYPE_INT32, &(pd->pw_uid),
+ DBUS_TYPE_INT32, &(pd->gr_gid),
DBUS_TYPE_INVALID);
return ret;
@@ -109,6 +113,8 @@ bool dp_unpack_pam_request(DBusMessage *msg, struct pam_data *pd, DBusError *dbu
&(pd->newauthtok),
&(pd->newauthtok_size),
DBUS_TYPE_INT32, &(pd->priv),
+ DBUS_TYPE_INT32, &(pd->pw_uid),
+ DBUS_TYPE_INT32, &(pd->gr_gid),
DBUS_TYPE_INVALID);
return ret;
diff --git a/server/providers/krb5/krb5_auth.c b/server/providers/krb5/krb5_auth.c
new file mode 100644
index 000000000..400e0cfb3
--- /dev/null
+++ b/server/providers/krb5/krb5_auth.c
@@ -0,0 +1,544 @@
+/*
+ SSSD
+
+ Kerberos 5 Backend Module
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2008 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#include <errno.h>
+#include <sys/time.h>
+#include <krb5/krb5.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+
+
+#include <security/pam_modules.h>
+
+#include "util/util.h"
+#include "providers/dp_backend.h"
+#include "db/sysdb.h"
+#include "../sss_client/sss_cli.h"
+
+#define MAX_CHILD_MSG_SIZE 255
+#define CCACHE_ENV_NAME "KRB5CCNAME"
+
+typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
+
+struct krb5_ctx {
+ /* opts taken from kinit */
+ /* in seconds */
+ krb5_deltat starttime;
+ krb5_deltat lifetime;
+ krb5_deltat rlife;
+
+ int forwardable;
+ int proxiable;
+ int addresses;
+
+ int not_forwardable;
+ int not_proxiable;
+ int no_addresses;
+
+ int verbose;
+
+ char* principal_name;
+ char* service_name;
+ char* keytab_name;
+ char* k5_cache_name;
+ char* k4_cache_name;
+
+ action_type action;
+
+ int num_pa_opts;
+ krb5_gic_opt_pa_data *pa_opts;
+
+};
+
+struct krb5_req {
+ krb5_context ctx;
+ krb5_ccache cc;
+ krb5_principal princ;
+ char* name;
+ krb5_creds *creds;
+ krb5_get_init_creds_opt *options;
+ pid_t child_pid;
+ int fd;
+
+ struct be_req *req;
+ struct pam_data *pd;
+ struct krb5_ctx *krb5_ctx;
+};
+
+static krb5_context krb5_error_ctx;
+static const char *__krb5_error_msg;
+#define KRB5_DEBUG(level, krb5_error) do { \
+ __krb5_error_msg = krb5_get_error_message(krb5_error_ctx, krb5_error); \
+ DEBUG(level, ("%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg)); \
+ krb5_free_error_message(krb5_error_ctx, __krb5_error_msg); \
+} while(0);
+
+static void fd_nonblocking(int fd) {
+ int flags;
+
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags == -1) {
+ DEBUG(1, ("F_GETFL failed [%d][%s].\n", errno, strerror(errno)));
+ return;
+ }
+
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
+ DEBUG(1, ("F_SETFL failed [%d][%s].\n", errno, strerror(errno)));
+ }
+
+ return;
+}
+
+static void krb5_cleanup(struct krb5_req *kr)
+{
+ if (kr == NULL) return;
+
+ if (kr->options != NULL)
+ krb5_get_init_creds_opt_free(kr->ctx, kr->options);
+ if (kr->creds != NULL)
+ krb5_free_cred_contents(kr->ctx, kr->creds);
+ if (kr->name != NULL)
+ krb5_free_unparsed_name(kr->ctx, kr->name);
+ if (kr->princ != NULL)
+ krb5_free_principal(kr->ctx, kr->princ);
+ if (kr->cc != NULL)
+ krb5_cc_close(kr->ctx, kr->cc);
+ if (kr->ctx != NULL)
+ krb5_free_context(kr->ctx);
+
+ if (kr != NULL) talloc_free(kr);
+}
+
+static int krb5_setup(struct be_req *req, struct krb5_req **krb5_req)
+{
+ struct krb5_req *kr = NULL;
+ struct krb5_ctx *krb5_ctx;
+ struct pam_data *pd;
+ krb5_error_code kerr = 0;
+ char *user_princ_str = NULL;
+
+ pd = talloc_get_type(req->req_data, struct pam_data);
+
+ krb5_ctx = talloc_get_type(req->be_ctx->pvt_auth_data, struct krb5_ctx);
+
+ kr = talloc_zero(req, struct krb5_req);
+ if (kr == NULL) {
+ DEBUG(1, ("talloc failed.\n"));
+ kerr = ENOMEM;
+ goto failed;
+ }
+
+ kr->pd = pd;
+ kr->req = req;
+
+ kerr = krb5_init_context(&kr->ctx);
+ if (kerr != 0) {
+ KRB5_DEBUG(1, kerr);
+ goto failed;
+ }
+
+ user_princ_str = talloc_asprintf(kr, "%s@IPATEST", kr->pd->user);
+ if (user_princ_str == NULL) {
+ DEBUG(1, ("talloc_asprintf failed.\n"));
+ kerr = ENOMEM;
+ goto failed;
+ }
+
+ kerr = krb5_parse_name(kr->ctx, user_princ_str, &kr->princ);
+ if (kerr != 0) {
+ KRB5_DEBUG(1, kerr);
+ goto failed;
+ }
+
+ kerr = krb5_unparse_name(kr->ctx, kr->princ, &kr->name);
+ if (kerr != 0) {
+ KRB5_DEBUG(1, kerr);
+ goto failed;
+ }
+
+ kr->creds = talloc_zero(kr, krb5_creds);
+ if (kr->creds == NULL) {
+ DEBUG(1, ("talloc_zero failed.\n"));
+ kerr = ENOMEM;
+ goto failed;
+ }
+
+ kerr = krb5_get_init_creds_opt_alloc(kr->ctx, &kr->options);
+ if (kerr != 0) {
+ KRB5_DEBUG(1, kerr);
+ goto failed;
+ }
+
+/* TODO: set options, e.g.
+ * krb5_get_init_creds_opt_set_tkt_life
+ * krb5_get_init_creds_opt_set_renew_life
+ * krb5_get_init_creds_opt_set_forwardable
+ * krb5_get_init_creds_opt_set_proxiable
+ * krb5_get_init_creds_opt_set_etype_list
+ * krb5_get_init_creds_opt_set_address_list
+ * krb5_get_init_creds_opt_set_preauth_list
+ * krb5_get_init_creds_opt_set_salt
+ * krb5_get_init_creds_opt_set_change_password_prompt
+ * krb5_get_init_creds_opt_set_pa
+ */
+
+ *krb5_req = kr;
+ return EOK;
+
+failed:
+ krb5_cleanup(kr);
+
+ return kerr;
+}
+
+static void client_response_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags,
+ void *private_data)
+{
+ struct krb5_req *kr = NULL;
+ struct be_req *req;
+ struct pam_data *pd;
+ int pam_status = PAM_SYSTEM_ERR;
+ int child_status;
+ int ret;
+ ssize_t size;
+ uint8_t buf[MAX_CHILD_MSG_SIZE];
+ int p;
+ int32_t *msg_status;
+ int32_t *msg_type;
+ int32_t *msg_len;
+
+ if (flags & TEVENT_FD_WRITE) {
+ DEBUG(1, ("client_response_handler called with TEVENT_FD_WRITE, this should not happen.\n"));
+ return;
+ }
+
+ kr = talloc_get_type(private_data, struct krb5_req);
+
+ req = kr->req;
+ pd = talloc_get_type(req->req_data, struct pam_data);
+
+ size = read(kr->fd, buf, sizeof(buf));
+ if (size == 0) {
+ DEBUG(1, ("empty response from child.\n"));
+ } else if (size == -1) {
+ if (errno == EAGAIN) return;
+ DEBUG(1, ("read failed [%d][%s].\n", errno, strerror(errno)));
+ }
+ close(kr->fd);
+ waitpid(kr->child_pid, &child_status, 0);
+ DEBUG(4, ("child status [%d].\n", child_status));
+ if (WEXITSTATUS(child_status) != 0) {
+ DEBUG(1, ("child failed.\n"));
+ goto done;
+ }
+
+ if ((size_t) size < 3*sizeof(int32_t)) {
+ DEBUG(1, ("message too short.\n"));
+ goto done;
+ }
+
+ p=0;
+ msg_status = ((int32_t *)(buf+p));
+ p += sizeof(int32_t);
+
+ msg_type = ((int32_t *)(buf+p));
+ p += sizeof(int32_t);
+
+ msg_len = ((int32_t *)(buf+p));
+ p += sizeof(int32_t);
+
+ DEBUG(4, ("child response [%d][%d][%d].\n", *msg_status, *msg_type,
+ *msg_len));
+
+ if ((p + *msg_len) != size) {
+ DEBUG(1, ("message format error.\n"));
+ goto done;
+ }
+
+ ret=pam_add_response(pd, *msg_type, *msg_len, &buf[p]);
+ if (ret != EOK) {
+ DEBUG(1, ("pam_add_response failed.\n"));
+ goto done;
+ }
+
+ pam_status = *msg_status;
+done:
+ krb5_cleanup(kr);
+
+ pd->pam_status = pam_status;
+
+ req->fn(req, pam_status, NULL);
+}
+
+int pack_response_packet(uint8_t *buf, int status, int type, const char *data)
+{
+ int len;
+ int p=0;
+
+ if ((3*sizeof(int32_t) + strlen(data)+1) > MAX_CHILD_MSG_SIZE) {
+ return -1;
+ }
+
+ ((int32_t *)(&buf[p]))[0] = status;
+ p += sizeof(int32_t);
+
+ ((int32_t *)(&buf[p]))[0] = type;
+ p += sizeof(int32_t);
+
+ len = strlen(data)+1;
+ ((int32_t *)(&buf[p]))[0] = len;
+ p += sizeof(int32_t);
+
+ memcpy(&buf[p], data, len);
+ p += len;
+
+ return p;
+}
+
+static void krb5_pam_handler(struct be_req *req)
+{
+ int ret;
+ int pam_status=PAM_SYSTEM_ERR;
+ struct krb5_req *kr = NULL;
+ struct krb5_ctx *krb5_ctx;
+ struct pam_data *pd;
+ krb5_error_code kerr = 0;
+ char *pass_str = NULL;
+ pid_t pid;
+ int pipefd[2];
+ struct tevent_fd *te;
+
+ uint8_t buf[MAX_CHILD_MSG_SIZE];
+ int size = 0;
+ const char *cc_name;
+ char *env;
+ const char *krb5_error_msg;
+
+ pd = talloc_get_type(req->req_data, struct pam_data);
+
+ if (pd->cmd != SSS_PAM_AUTHENTICATE) {
+ DEBUG(4, ("krb5 does not handles pam task %d.\n", pd->cmd));
+ pam_status = PAM_SUCCESS;
+ goto done;
+ }
+
+ krb5_ctx = talloc_get_type(req->be_ctx->pvt_auth_data, struct krb5_ctx);
+
+ ret = krb5_setup(req, &kr);
+ if (ret != EOK) {
+ DEBUG(1, ("krb5_setup failed.\n"));
+ goto done;
+ }
+
+ ret = pipe(pipefd);
+ if (ret == -1) {
+ DEBUG(1, ("pipe failed [%d][%s].\n", errno, strerror(errno)));
+ goto done;
+ }
+ pid = fork();
+
+ if (pid == 0) { /* child */
+ close(pipefd[0]);
+
+ ret = setgid(pd->gr_gid);
+ if (ret == -1) {
+ DEBUG(1, ("setgid failed [%d][%s].\n", errno, strerror(errno)));
+ _exit(-1);
+ }
+
+ ret = setuid(pd->pw_uid);
+ if (ret == -1) {
+ DEBUG(1, ("setuid failed [%d][%s].\n", errno, strerror(errno)));
+ _exit(-1);
+ }
+
+ ret = setegid(pd->gr_gid);
+ if (ret == -1) {
+ DEBUG(1, ("setegid failed [%d][%s].\n", errno, strerror(errno)));
+ _exit(-1);
+ }
+
+ ret = seteuid(pd->pw_uid);
+ if (ret == -1) {
+ DEBUG(1, ("seteuid failed [%d][%s].\n", errno, strerror(errno)));
+ _exit(-1);
+ }
+
+ pass_str = talloc_strndup(kr, (const char *) kr->pd->authtok,
+ kr->pd->authtok_size);
+ if (pass_str == NULL) {
+ DEBUG(1, ("talloc_strndup failed.\n"));
+ _exit(-1);
+ }
+
+ kerr = krb5_get_init_creds_password(kr->ctx, kr->creds, kr->princ,
+ pass_str, NULL, NULL, 0, NULL,
+ kr->options);
+ if (kerr != 0) {
+ KRB5_DEBUG(1, kerr);
+ //_exit(kerr);
+ goto childfailed;
+ }
+
+ memset(pass_str, 0, kr->pd->authtok_size);
+ talloc_free(pass_str);
+ memset(kr->pd->authtok, 0, kr->pd->authtok_size);
+
+ kerr = krb5_cc_default(kr->ctx, &kr->cc);
+ if (kerr != 0) {
+ KRB5_DEBUG(1, kerr);
+ //_exit(kerr);
+ goto childfailed;
+ }
+
+ kerr = krb5_cc_initialize(kr->ctx, kr->cc, kr->princ);
+ if (kerr != 0) {
+ KRB5_DEBUG(1, kerr);
+ //_exit(kerr);
+ goto childfailed;
+ }
+
+ kerr = krb5_cc_store_cred(kr->ctx, kr->cc, kr->creds);
+ if (kerr != 0) {
+ KRB5_DEBUG(1, kerr);
+ krb5_cc_destroy(kr->ctx, kr->cc);
+ //_exit(kerr);
+ goto childfailed;
+ }
+
+ cc_name = krb5_cc_get_name(kr->ctx, kr->cc);
+ if (cc_name == NULL) {
+ DEBUG(1, ("krb5_cc_get_name failed.\n"));
+ krb5_cc_destroy(kr->ctx, kr->cc);
+ _exit(-1);
+ }
+
+ env = talloc_asprintf(kr, "%s=%s",CCACHE_ENV_NAME, cc_name);
+ if (env == NULL) {
+ DEBUG(1, ("talloc_asprintf failed.\n"));
+ krb5_cc_destroy(kr->ctx, kr->cc);
+ _exit(-1);
+ }
+
+ size = pack_response_packet(buf, PAM_SUCCESS, PAM_ENV_ITEM, env);
+ if (size < 0) {
+ DEBUG(1, ("failed to create response message.\n"));
+ krb5_cc_destroy(kr->ctx, kr->cc);
+ _exit(-1);
+ }
+
+ kerr = 0;
+
+childfailed:
+ if (kerr != 0 ) {
+ krb5_error_msg = krb5_get_error_message(krb5_error_ctx, kerr);
+ size = pack_response_packet(buf, PAM_SYSTEM_ERR, PAM_USER_INFO,
+ krb5_error_msg);
+ if (size < 0) {
+ DEBUG(1, ("failed to create response message.\n"));
+ krb5_cc_destroy(kr->ctx, kr->cc);
+ _exit(-1);
+ }
+ krb5_free_error_message(krb5_error_ctx, krb5_error_msg);
+ }
+
+ ret = write(pipefd[1], buf, size);
+ if (ret == -1) {
+ DEBUG(1, ("write failed [%d][%s].\n", errno, strerror(errno)));
+ krb5_cc_destroy(kr->ctx, kr->cc);
+ _exit(ret);
+ }
+
+ krb5_cc_close(kr->ctx, kr->cc);
+
+
+ _exit(0);
+
+ } else if (pid > 0) { /* parent */
+ kr->child_pid = pid;
+ kr->fd = pipefd[0];
+ close(pipefd[1]);
+
+ fd_nonblocking(kr->fd);
+
+ te = tevent_add_fd(req->be_ctx->ev, kr, kr->fd, TEVENT_FD_READ,
+ client_response_handler, kr);
+ if (te == NULL) {
+ DEBUG(1, ("tevent_add_fd failed.\n"));
+ goto done;
+ }
+
+ return;
+ } else { /* error */
+ DEBUG(1, ("fork failed [%d][%s].\n", errno, strerror(errno)));
+ goto done;
+ }
+
+ pam_status = PAM_SUCCESS;
+
+done:
+ krb5_cleanup(kr);
+
+ pd->pam_status = pam_status;
+
+ req->fn(req, pam_status, NULL);
+}
+
+struct be_auth_ops krb5_auth_ops = {
+ .pam_handler = krb5_pam_handler,
+ .finalize = NULL,
+};
+
+
+int sssm_krb5_auth_init(struct be_ctx *bectx, struct be_auth_ops **ops,
+ void **pvt_auth_data)
+{
+ struct krb5_ctx *ctx;
+ int ret;
+
+ ctx = talloc_zero(bectx, struct krb5_ctx);
+ if (!ctx) {
+ DEBUG(1, ("talloc failed.\n"));
+ return ENOMEM;
+ }
+
+ ctx->action = INIT_PW;
+
+/* TODO: set options */
+
+ *ops = &krb5_auth_ops;
+ *pvt_auth_data = ctx;
+ return EOK;
+
+ if (ret != EOK) {
+ talloc_free(ctx);
+ }
+ return ret;
+}
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index 1df947ad3..8773a6bf2 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -22,6 +22,7 @@
#include <time.h>
#include "util/util.h"
+#include "db/sysdb.h"
#include "confdb/confdb.h"
#include "responder/common/responder_packet.h"
#include "responder/common/responder.h"
@@ -387,7 +388,6 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
size_t blen;
int timeout;
int ret;
-
preq = talloc_zero(cctx, struct pam_auth_req);
if (!preq) {
return ENOMEM;
@@ -710,6 +710,24 @@ static void pam_check_user_callback(void *ptr, int status,
case 1:
/* BINGO */
+ preq->pd->pw_uid =
+ ldb_msg_find_attr_as_int(res->msgs[0], SYSDB_UIDNUM, -1);
+ if (preq->pd->pw_uid == -1) {
+ DEBUG(1, ("Failed to find uid for user [%s] in domain [%s].\n",
+ preq->pd->user, preq->pd->domain));
+ preq->pd->pam_status = PAM_SYSTEM_ERR;
+ pam_reply(preq);
+ }
+
+ preq->pd->gr_gid =
+ ldb_msg_find_attr_as_int(res->msgs[0], SYSDB_GIDNUM, -1);
+ if (preq->pd->gr_gid == -1) {
+ DEBUG(1, ("Failed to find gid for user [%s] in domain [%s].\n",
+ preq->pd->user, preq->pd->domain));
+ preq->pd->pam_status = PAM_SYSTEM_ERR;
+ pam_reply(preq);
+ }
+
pam_dom_forwarder(preq);
return;
diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c
index cf5c6a484..a3ae9cc42 100644
--- a/sss_client/pam_sss.c
+++ b/sss_client/pam_sss.c
@@ -425,7 +425,7 @@ static int eval_response(pam_handle_t *pamh, size_t buflen, uint8_t *buf)
break;
}
logger(pamh, LOG_INFO, "user info: [%s]", &buf[p]);
- ret = do_pam_conversation(pamh, PAM_USER_INFO, (char *) &buf[p],
+ ret = do_pam_conversation(pamh, PAM_TEXT_INFO, (char *) &buf[p],
NULL, NULL);
if (ret != PAM_SUCCESS) {
D(("do_pam_conversation, canot display user info."));
diff --git a/sssd.spec.in b/sssd.spec.in
index 4a3974e2a..144a75a44 100644
--- a/sssd.spec.in
+++ b/sssd.spec.in
@@ -105,6 +105,7 @@ rm -rf $RPM_BUILD_ROOT
%{_libexecdir}/%{servicename}/
%{_libdir}/%{name}/
%{_libdir}/ldb/memberof.so
+%{_libdir}/krb5/plugins/libkrb5/*
%dir %{_sharedstatedir}/sss/
%attr(700,root,root) %dir %{_sharedstatedir}/sss/db
%dir %{_sharedstatedir}/sss/pipes
@@ -164,3 +165,18 @@ fi
* Thu Feb 12 2009 Stephen Gallagher <sgallagh@redhat.com> - 0.1.0-1
- Initial release (based on version 0.1.0 upstream code)
+* Tue Mar 10 2009 Simo Sorce <ssorce@redhat.com> - 0.2.1-1
+- Bump up to version 0.2.1
+
+* Fri Mar 06 2009 Jakub Hrozek <jhrozek@redhat.com> - 0.1.0-4
+- fixed items found during review
+- added initscript
+
+* Thu Mar 05 2009 Sumit Bose <sbose@redhat.com> - 0.1.0-3
+- added sss_client
+
+* Mon Feb 23 2009 Jakub Hrozek <jhrozek@redhat.com> - 0.1.0-2
+- Small cleanup and fixes in the spec file
+
+* Thu Feb 12 2009 Stephen Gallagher <sgallagh@redhat.com> - 0.1.0-1
+- Initial release (based on version 0.1.0 upstream code)