diff options
author | Sumit Bose <sbose@redhat.com> | 2009-03-18 13:59:48 +0100 |
---|---|---|
committer | Sumit Bose <sbose@redhat.com> | 2009-06-08 15:36:27 +0200 |
commit | 272d66315d6e8394dbcd5661103119a91a279108 (patch) | |
tree | 223321a92c5dcd6a5ef3293101c3d4e7418da826 | |
parent | 7fc0bcafaf0b186d8dfa4f6a42ab30f33164475f (diff) | |
download | sssd-272d66315d6e8394dbcd5661103119a91a279108.tar.gz sssd-272d66315d6e8394dbcd5661103119a91a279108.tar.xz sssd-272d66315d6e8394dbcd5661103119a91a279108.zip |
added kerberos backend and kdc locator plugin
-rw-r--r-- | server/Makefile.am | 27 | ||||
-rw-r--r-- | server/conf_macros.m4 | 14 | ||||
-rw-r--r-- | server/configure.ac | 2 | ||||
-rw-r--r-- | server/external/krb5.m4 | 11 | ||||
-rw-r--r-- | server/krb5_plugin/sssd_krb5_locator_plugin.c | 129 | ||||
-rw-r--r-- | server/providers/data_provider.h | 2 | ||||
-rw-r--r-- | server/providers/dp_auth_util.c | 6 | ||||
-rw-r--r-- | server/providers/krb5/krb5_auth.c | 544 | ||||
-rw-r--r-- | server/responder/pam/pamsrv_cmd.c | 20 | ||||
-rw-r--r-- | sss_client/pam_sss.c | 2 | ||||
-rw-r--r-- | sssd.spec.in | 16 |
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) |