SHA256
1
0
forked from jengelh/sssd

Accepting request 47051 from network:ldap

checked in (request 47051)

OBS-URL: https://build.opensuse.org/request/show/47051
OBS-URL: https://build.opensuse.org/package/show/network:ldap/sssd?expand=0&rev=25
This commit is contained in:
OBS User autobuild 2010-09-03 14:48:37 +00:00 committed by Git OBS Bridge
parent 9fd36947ac
commit 1657917db2
8 changed files with 964 additions and 127 deletions

View File

@ -0,0 +1,451 @@
From bf75a22ffc04dfa0387a1389750b0a1e6d3ac397 Mon Sep 17 00:00:00 2001
From: Ralf Haferkamp <rhafer@suse.de>
Date: Fri, 26 Mar 2010 15:04:51 +0100
Subject: [PATCH] Added option to use libcrypto instead of NSS.
crypto_sha512crypt.c is a clone of nss_sha512crypt.c with the exception that
all usage of NSS and related libraries has been switched to libcrypto.
I renamed nss_sha512crypt.h to sha512crypt.h since it is common to both
crypto_sha512crypt.c and nss_sha512crypt.c. Note that the random number
generator is not seeded manually and thus relies on seeding done
automatically by libcrypto. On some systems without /dev/urandom
seeding may not be performed.
See http://www.openssl.org/docs/crypto/RAND_add.html.
Signed-off-by: George McCollister <georgem@novatech-llc.com>
Conflicts:
server/util/nss_sha512crypt.h
server/util/sha512crypt.h
src/Makefile.am
src/configure.ac
src/util/sha512crypt.h
---
server/external/crypto.m4 | 13 ++
server/util/crypto_sha512crypt.c | 382 ++++++++++++++++++++++++++++++++++++++
server/util/sha512crypt.h | 4 +
3 files changed, 399 insertions(+), 0 deletions(-)
create mode 100644 server/external/crypto.m4
create mode 100644 server/util/crypto_sha512crypt.c
create mode 100644 server/util/sha512crypt.h
diff --git a/server/external/crypto.m4 b/server/external/crypto.m4
new file mode 100644
index 0000000..d1bcf40
--- /dev/null
+++ b/server/external/crypto.m4
@@ -0,0 +1,13 @@
+AC_ARG_ENABLE(crypto,
+ [ --enable-crypto Use OpenSSL crypto instead of NSS],
+ [CRYPTO="$enableval"],
+ [CRYPTO="no"]
+)
+
+if test x$CRYPTO != xyes; then
+ PKG_CHECK_MODULES([NSS],[nss],[have_nss=1],[have_nss=])
+else
+ PKG_CHECK_MODULES([CRYPTO],[libcrypto],[have_crypto=1],[have_crypto=])
+fi
+AM_CONDITIONAL([HAVE_NSS], [test x$have_nss != x])
+AM_CONDITIONAL([HAVE_CRYPTO], [test x$have_crypto != x])
diff --git a/server/util/crypto_sha512crypt.c b/server/util/crypto_sha512crypt.c
new file mode 100644
index 0000000..9cd03a1
--- /dev/null
+++ b/server/util/crypto_sha512crypt.c
@@ -0,0 +1,382 @@
+/* This file is based on nss_sha512crypt.c which is based on the work of
+ * Ulrich Drepper (http://people.redhat.com/drepper/SHA-crypt.txt).
+ *
+ * libcrypto is used to provide SHA512 and random number generation.
+ * (http://www.openssl.org/docs/crypto/crypto.html).
+ *
+ * Sumit Bose <sbose@redhat.com>
+ * George McCollister <georgem@novatech-llc.com>
+ */
+/* SHA512-based Unix crypt implementation.
+ Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>. */
+
+#define _GNU_SOURCE
+#include <endian.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include "util/util.h"
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+/* Define our magic string to mark salt for SHA512 "encryption" replacement. */
+const char sha512_salt_prefix[] = "$6$";
+#define SALT_PREF_SIZE (sizeof(sha512_salt_prefix) - 1)
+
+/* Prefix for optional rounds specification. */
+const char sha512_rounds_prefix[] = "rounds=";
+#define ROUNDS_SIZE (sizeof(sha512_rounds_prefix) - 1)
+
+#define SALT_LEN_MAX 16
+#define ROUNDS_DEFAULT 5000
+#define ROUNDS_MIN 1000
+#define ROUNDS_MAX 999999999
+
+/* Table with characters for base64 transformation. */
+const char b64t[64] =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+/* base64 conversion function */
+static inline void b64_from_24bit(char **dest, size_t *len, size_t n,
+ uint8_t b2, uint8_t b1, uint8_t b0)
+{
+ uint32_t w;
+ size_t i;
+
+ if (*len < n) n = *len;
+
+ w = (b2 << 16) | (b1 << 8) | b0;
+ for (i = 0; i < n; i++) {
+ (*dest)[i] = b64t[w & 0x3f];
+ w >>= 6;
+ }
+
+ *len -= i;
+ *dest += i;
+}
+
+#define PTR_2_INT(x) ((x) - ((__typeof__ (x)) NULL))
+#define ALIGN64 __alignof__(uint64_t)
+
+static int sha512_crypt_r(const char *key,
+ const char *salt,
+ char *buffer, size_t buflen)
+{
+ unsigned char temp_result[64] __attribute__((__aligned__(ALIGN64)));
+ unsigned char alt_result[64] __attribute__((__aligned__(ALIGN64)));
+ size_t rounds = ROUNDS_DEFAULT;
+ bool rounds_custom = false;
+ EVP_MD_CTX alt_ctx;
+ EVP_MD_CTX ctx;
+ size_t salt_len;
+ size_t key_len;
+ size_t cnt;
+ char *copied_salt = NULL;
+ char *copied_key = NULL;
+ char *p_bytes = NULL;
+ char *s_bytes = NULL;
+ int p1, p2, p3, pt, n;
+ unsigned int part;
+ char *cp, *tmp;
+ int ret;
+
+ /* Find beginning of salt string. The prefix should normally always be
+ * present. Just in case it is not. */
+ if (strncmp(salt, sha512_salt_prefix, SALT_PREF_SIZE) == 0) {
+ /* Skip salt prefix. */
+ salt += SALT_PREF_SIZE;
+ }
+
+ if (strncmp(salt, sha512_rounds_prefix, ROUNDS_SIZE) == 0) {
+ unsigned long int srounds;
+ const char *num;
+ char *endp;
+
+ num = salt + ROUNDS_SIZE;
+ srounds = strtoul(num, &endp, 10);
+ if (*endp == '$') {
+ salt = endp + 1;
+ if (srounds < ROUNDS_MIN) srounds = ROUNDS_MIN;
+ if (srounds > ROUNDS_MAX) srounds = ROUNDS_MAX;
+ rounds = srounds;
+ rounds_custom = true;
+ }
+ }
+
+ salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
+ key_len = strlen(key);
+
+ if ((PTR_2_INT(key) % ALIGN64) != 0) {
+ tmp = (char *)alloca(key_len + ALIGN64);
+ key = copied_key = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, key, key_len);
+ }
+
+ if (PTR_2_INT(salt) % ALIGN64 != 0) {
+ tmp = (char *)alloca(salt_len + ALIGN64);
+ salt = copied_salt = memcpy(tmp + ALIGN64 - PTR_2_INT(tmp) % ALIGN64, salt, salt_len);
+ }
+
+ EVP_MD_CTX_init(&ctx);
+
+ EVP_MD_CTX_init(&alt_ctx);
+
+ /* Prepare for the real work. */
+ if (!EVP_DigestInit_ex(&ctx, EVP_sha512(), NULL)) {
+ ret = EIO;
+ goto done;
+ }
+
+ /* Add the key string. */
+ EVP_DigestUpdate(&ctx, (const unsigned char *)key, key_len);
+
+ /* The last part is the salt string. This must be at most 16
+ * characters and it ends at the first `$' character (for
+ * compatibility with existing implementations). */
+ EVP_DigestUpdate(&ctx, (const unsigned char *)salt, salt_len);
+
+
+ /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.
+ * The final result will be added to the first context. */
+ if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
+ ret = EIO;
+ goto done;
+ }
+
+ /* Add key. */
+ EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
+
+ /* Add salt. */
+ EVP_DigestUpdate(&alt_ctx, (const unsigned char *)salt, salt_len);
+
+ /* Add key again. */
+ EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
+
+ /* Now get result of this (64 bytes) and add it to the other context. */
+ EVP_DigestFinal_ex(&alt_ctx, alt_result, &part);
+
+ /* Add for any character in the key one byte of the alternate sum. */
+ for (cnt = key_len; cnt > 64; cnt -= 64) {
+ EVP_DigestUpdate(&ctx, alt_result, 64);
+ }
+ EVP_DigestUpdate(&ctx, alt_result, cnt);
+
+ /* Take the binary representation of the length of the key and for every
+ * 1 add the alternate sum, for every 0 the key. */
+ for (cnt = key_len; cnt > 0; cnt >>= 1) {
+ if ((cnt & 1) != 0) {
+ EVP_DigestUpdate(&ctx, alt_result, 64);
+ } else {
+ EVP_DigestUpdate(&ctx, (const unsigned char *)key, key_len);
+ }
+ }
+
+ /* Create intermediate result. */
+ EVP_DigestFinal_ex(&ctx, alt_result, &part);
+
+ /* Start computation of P byte sequence. */
+ if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
+ ret = EIO;
+ goto done;
+ }
+
+ /* For every character in the password add the entire password. */
+ for (cnt = 0; cnt < key_len; cnt++) {
+ EVP_DigestUpdate(&alt_ctx, (const unsigned char *)key, key_len);
+ }
+
+ /* Finish the digest. */
+ EVP_DigestFinal_ex(&alt_ctx, temp_result, &part);
+
+ /* Create byte sequence P. */
+ cp = p_bytes = alloca(key_len);
+ for (cnt = key_len; cnt >= 64; cnt -= 64) {
+ cp = mempcpy(cp, temp_result, 64);
+ }
+ memcpy(cp, temp_result, cnt);
+
+ /* Start computation of S byte sequence. */
+ if (!EVP_DigestInit_ex(&alt_ctx, EVP_sha512(), NULL)) {
+ ret = EIO;
+ goto done;
+ }
+
+ /* For every character in the password add the entire salt. */
+ for (cnt = 0; cnt < 16 + alt_result[0]; cnt++) {
+ EVP_DigestUpdate(&alt_ctx, (const unsigned char *)salt, salt_len);
+ }
+
+ /* Finish the digest. */
+ EVP_DigestFinal_ex(&alt_ctx, temp_result, &part);
+
+ /* Create byte sequence S. */
+ cp = s_bytes = alloca(salt_len);
+ for (cnt = salt_len; cnt >= 64; cnt -= 64) {
+ cp = mempcpy(cp, temp_result, 64);
+ }
+ memcpy(cp, temp_result, cnt);
+
+ /* Repeatedly run the collected hash value through SHA512 to burn CPU cycles. */
+ for (cnt = 0; cnt < rounds; cnt++) {
+
+ if (!EVP_DigestInit_ex(&ctx, EVP_sha512(), NULL)) {
+ ret = EIO;
+ goto done;
+ }
+
+ /* Add key or last result. */
+ if ((cnt & 1) != 0) {
+ EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
+ } else {
+ EVP_DigestUpdate(&ctx, alt_result, 64);
+ }
+
+ /* Add salt for numbers not divisible by 3. */
+ if (cnt % 3 != 0) {
+ EVP_DigestUpdate(&ctx, (const unsigned char *)s_bytes, salt_len);
+ }
+
+ /* Add key for numbers not divisible by 7. */
+ if (cnt % 7 != 0) {
+ EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
+ }
+
+ /* Add key or last result. */
+ if ((cnt & 1) != 0) {
+ EVP_DigestUpdate(&ctx, alt_result, 64);
+ } else {
+ EVP_DigestUpdate(&ctx, (const unsigned char *)p_bytes, key_len);
+ }
+
+ /* Create intermediate result. */
+ EVP_DigestFinal_ex(&ctx, alt_result, &part);
+ }
+
+ /* Now we can construct the result string.
+ * It consists of three parts. */
+ if (buflen <= SALT_PREF_SIZE) {
+ ret = ERANGE;
+ goto done;
+ }
+
+ cp = __stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
+ buflen -= SALT_PREF_SIZE;
+
+ if (rounds_custom) {
+ n = snprintf(cp, buflen, "%s%zu$",
+ sha512_rounds_prefix, rounds);
+ if (n < 0 || n >= buflen) {
+ ret = ERANGE;
+ goto done;
+ }
+ cp += n;
+ buflen -= n;
+ }
+
+ if (buflen <= salt_len + 1) {
+ ret = ERANGE;
+ goto done;
+ }
+ cp = __stpncpy(cp, salt, salt_len);
+ *cp++ = '$';
+ buflen -= salt_len + 1;
+
+ /* fuzzyfill the base 64 string */
+ p1 = 0;
+ p2 = 21;
+ p3 = 42;
+ for (n = 0; n < 21; n++) {
+ b64_from_24bit(&cp, &buflen, 4, alt_result[p1], alt_result[p2], alt_result[p3]);
+ if (buflen == 0) {
+ ret = ERANGE;
+ goto done;
+ }
+ pt = p1;
+ p1 = p2 + 1;
+ p2 = p3 + 1;
+ p3 = pt + 1;
+ }
+ /* 64th and last byte */
+ b64_from_24bit(&cp, &buflen, 2, 0, 0, alt_result[p3]);
+ if (buflen == 0) {
+ ret = ERANGE;
+ goto done;
+ }
+
+ *cp = '\0';
+ ret = EOK;
+
+done:
+ /* Clear the buffer for the intermediate result so that people attaching
+ * to processes or reading core dumps cannot get any information. We do it
+ * in this way to clear correct_words[] inside the SHA512 implementation
+ * as well. */
+ EVP_MD_CTX_cleanup(&ctx);
+ EVP_MD_CTX_cleanup(&alt_ctx);
+ if (p_bytes) memset(p_bytes, '\0', key_len);
+ if (s_bytes) memset(s_bytes, '\0', salt_len);
+ if (copied_key) memset(copied_key, '\0', key_len);
+ if (copied_salt) memset(copied_salt, '\0', salt_len);
+ memset(temp_result, '\0', sizeof(temp_result));
+
+ return ret;
+}
+
+int s3crypt_sha512(TALLOC_CTX *memctx,
+ const char *key, const char *salt, char **_hash)
+{
+ char *hash;
+ int hlen = (sizeof (sha512_salt_prefix) - 1
+ + sizeof (sha512_rounds_prefix) + 9 + 1
+ + strlen (salt) + 1 + 86 + 1);
+ int ret;
+
+ hash = talloc_size(memctx, hlen);
+ if (!hash) return ENOMEM;
+
+ ret = sha512_crypt_r(key, salt, hash, hlen);
+ if (ret) return ret;
+
+ *_hash = hash;
+ return ret;
+}
+
+#define SALT_RAND_LEN 12
+
+int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt)
+{
+ uint8_t rb[SALT_RAND_LEN];
+ char *salt, *cp;
+ size_t slen;
+ int ret;
+
+ salt = talloc_size(memctx, SALT_LEN_MAX + 1);
+ if (!salt) {
+ return ENOMEM;
+ }
+
+ ret = RAND_bytes(rb, SALT_RAND_LEN);
+ if (ret == 0) {
+ return EIO;
+ }
+
+ slen = SALT_LEN_MAX;
+ cp = salt;
+ b64_from_24bit(&cp, &slen, 4, rb[0], rb[1], rb[2]);
+ b64_from_24bit(&cp, &slen, 4, rb[3], rb[4], rb[5]);
+ b64_from_24bit(&cp, &slen, 4, rb[6], rb[7], rb[8]);
+ b64_from_24bit(&cp, &slen, 4, rb[9], rb[10], rb[11]);
+ *cp = '\0';
+
+ *_salt = salt;
+
+ return EOK;
+}
+
diff --git a/server/util/sha512crypt.h b/server/util/sha512crypt.h
new file mode 100644
index 0000000..5512c5d
--- /dev/null
+++ b/server/util/sha512crypt.h
@@ -0,0 +1,4 @@
+
+int s3crypt_sha512(TALLOC_CTX *mmectx,
+ const char *key, const char *salt, char **_hash);
+int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt);
--
1.7.0.2

View File

@ -0,0 +1,415 @@
From 536c01cf9a04573c2351542fe00973e1538014a5 Mon Sep 17 00:00:00 2001
From: Ralf Haferkamp <rhafer@suse.de>
Date: Fri, 12 Mar 2010 10:54:40 +0100
Subject: [PATCH] Improvements for LDAP Password Policy support
Display warnings about remaining grace logins and password
expiration to the user, when LDAP Password Policies are used.
Improved detection if LDAP Password policies are supported by
LDAP Server.
---
src/providers/ldap/ldap_auth.c | 52 +++++++++++++++++-
src/providers/ldap/sdap.h | 5 ++
src/providers/ldap/sdap_async.h | 6 ++-
src/providers/ldap/sdap_async_connection.c | 53 +++++++++++++++----
src/sss_client/pam_sss.c | 82 ++++++++++++++++++++++++++++
src/sss_client/sss_cli.h | 23 ++++++---
6 files changed, 201 insertions(+), 20 deletions(-)
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index 5228703..8c77e3a 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -7,6 +7,7 @@
Sumit Bose <sbose@redhat.com>
Copyright (C) 2008 Red Hat
+ Copyright (C) 2010, rhafer@suse.de, Novell Inc.
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
@@ -135,6 +136,39 @@ static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now,
return EOK;
}
+static errno_t check_pwexpire_ldap(struct pam_data *pd,
+ struct sdap_ppolicy_data *ppolicy,
+ enum sdap_result *result)
+{
+ if (ppolicy->grace > 0 || ppolicy->expire > 0) {
+ uint32_t *data;
+ uint32_t *ptr;
+
+ data = talloc_size(pd, 2* sizeof(uint32_t));
+ if (data == NULL) {
+ DEBUG(1, ("talloc_size failed.\n"));
+ return ENOMEM;
+ }
+
+ ptr = data;
+ if (ppolicy->grace > 0) {
+ *ptr = SSS_PAM_USER_INFO_GRACE_LOGIN;
+ ptr++;
+ *ptr = ppolicy->grace;
+ } else if (ppolicy->expire > 0) {
+ *ptr = SSS_PAM_USER_INFO_EXPIRE_WARN;
+ ptr++;
+ *ptr = ppolicy->expire;
+ }
+
+ pam_add_response(pd, SSS_PAM_USER_INFO, 2* sizeof(uint32_t),
+ (uint8_t*)data);
+ }
+
+ *result = SDAP_AUTH_SUCCESS;
+ return EOK;
+}
+
static errno_t string_to_shadowpw_days(const char *s, long *d)
{
long l;
@@ -569,8 +603,15 @@ static void auth_bind_user_done(struct tevent_req *subreq)
struct auth_state *state = tevent_req_data(req,
struct auth_state);
int ret;
-
- ret = sdap_auth_recv(subreq, &state->result);
+ struct sdap_ppolicy_data *ppolicy;
+
+ ret = sdap_auth_recv(subreq, state, &state->result, &ppolicy);
+ if (ppolicy != NULL) {
+ DEBUG(9,("Found ppolicy data, "
+ "assuming LDAP password policies are active.\n"));
+ state->pw_expire_type = PWEXPIRE_LDAP_PASSWORD_POLICY;
+ state->pw_expire_data = ppolicy;
+ }
talloc_zfree(subreq);
if (ret) {
tevent_req_error(req, ret);
@@ -960,6 +1001,13 @@ static void sdap_pam_auth_done(struct tevent_req *req)
}
break;
case PWEXPIRE_LDAP_PASSWORD_POLICY:
+ ret = check_pwexpire_ldap(state->pd, pw_expire_data, &result);
+ if (ret != EOK) {
+ DEBUG(1, ("check_pwexpire_ldap failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+ break;
case PWEXPIRE_NONE:
break;
default:
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 007185f..f0e345e 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -85,6 +85,11 @@ struct sdap_service {
char *uri;
};
+struct sdap_ppolicy_data {
+ int grace;
+ int expire;
+};
+
#define SYSDB_SHADOWPW_LASTCHANGE "shadowLastChange"
#define SYSDB_SHADOWPW_MIN "shadowMin"
#define SYSDB_SHADOWPW_MAX "shadowMax"
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 3c52d23..888df6b 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -76,7 +76,11 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
const char *user_dn,
const char *authtok_type,
struct dp_opt_blob authtok);
-int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result);
+
+int sdap_auth_recv(struct tevent_req *req,
+ TALLOC_CTX *memctx,
+ enum sdap_result *result,
+ struct sdap_ppolicy_data **ppolicy);
struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 586733f..f8c6956 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -4,6 +4,7 @@
Async LDAP Helper routines
Copyright (C) Simo Sorce <ssorce@redhat.com> - 2009
+ Copyright (C) 2010, rhafer@suse.de, Novell Inc.
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
@@ -278,6 +279,7 @@ struct simple_bind_state {
struct sdap_op *op;
struct sdap_msg *reply;
+ struct sdap_ppolicy_data *ppolicy;
int result;
};
@@ -401,6 +403,7 @@ static void simple_bind_done(struct sdap_op *op,
if (response_controls == NULL) {
DEBUG(5, ("Server returned no controls.\n"));
+ state->ppolicy = NULL;
} else {
for (c = 0; response_controls[c] != NULL; c++) {
DEBUG(9, ("Server returned control [%s].\n",
@@ -420,12 +423,30 @@ static void simple_bind_done(struct sdap_op *op,
DEBUG(7, ("Password Policy Response: expire [%d] grace [%d] "
"error [%s].\n", pp_expire, pp_grace,
ldap_passwordpolicy_err2txt(pp_error)));
-
- if ((state->result == LDAP_SUCCESS &&
- (pp_error == PP_changeAfterReset || pp_grace > 0)) ||
- (state->result == LDAP_INVALID_CREDENTIALS &&
- pp_error == PP_passwordExpired ) ) {
- DEBUG(4, ("User must set a new password.\n"));
+ state->ppolicy = talloc(state, struct sdap_ppolicy_data);
+ if (state->ppolicy == NULL) {
+ DEBUG(1, ("talloc failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ state->ppolicy->grace = pp_grace;
+ state->ppolicy->expire = pp_expire;
+ if (state->result == LDAP_SUCCESS) {
+ if (pp_error == PP_changeAfterReset) {
+ DEBUG(4, ("Password was reset. "
+ "User must set a new password.\n"));
+ state->result = LDAP_X_SSSD_PASSWORD_EXPIRED;
+ } else if (pp_grace > 0) {
+ DEBUG(4, ("Password expired. "
+ "[%d] grace logins remaining.\n", pp_grace));
+ } else if (pp_expire > 0) {
+ DEBUG(4, ("Password will expire in [%d] seconds.\n",
+ pp_expire));
+ }
+ } else if (state->result == LDAP_INVALID_CREDENTIALS &&
+ pp_error == PP_passwordExpired) {
+ DEBUG(4,
+ ("Password expired user must set a new password.\n"));
state->result = LDAP_X_SSSD_PASSWORD_EXPIRED;
}
}
@@ -446,7 +467,10 @@ done:
}
}
-static int simple_bind_recv(struct tevent_req *req, int *ldaperr)
+static int simple_bind_recv(struct tevent_req *req,
+ TALLOC_CTX *memctx,
+ int *ldaperr,
+ struct sdap_ppolicy_data **ppolicy)
{
struct simple_bind_state *state = tevent_req_data(req,
struct simple_bind_state);
@@ -455,6 +479,7 @@ static int simple_bind_recv(struct tevent_req *req, int *ldaperr)
TEVENT_REQ_RETURN_ON_ERROR(req);
*ldaperr = state->result;
+ *ppolicy = talloc_steal(memctx, state->ppolicy);
return EOK;
}
@@ -704,6 +729,7 @@ int sdap_kinit_recv(struct tevent_req *req, enum sdap_result *result)
struct sdap_auth_state {
const char *user_dn;
struct berval pw;
+ struct sdap_ppolicy_data *ppolicy;
int result;
bool is_sasl;
@@ -766,8 +792,9 @@ static void sdap_auth_done(struct tevent_req *subreq)
if (state->is_sasl) {
ret = sasl_bind_recv(subreq, &state->result);
+ state->ppolicy = NULL;
} else {
- ret = simple_bind_recv(subreq, &state->result);
+ ret = simple_bind_recv(subreq, state, &state->result, &state->ppolicy);
}
if (ret != EOK) {
tevent_req_error(req, ret);
@@ -777,7 +804,10 @@ static void sdap_auth_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result)
+int sdap_auth_recv(struct tevent_req *req,
+ TALLOC_CTX *memctx,
+ enum sdap_result *result,
+ struct sdap_ppolicy_data **ppolicy)
{
struct sdap_auth_state *state = tevent_req_data(req,
struct sdap_auth_state);
@@ -785,6 +815,9 @@ int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result)
*result = SDAP_ERROR;
TEVENT_REQ_RETURN_ON_ERROR(req);
+ if (ppolicy != NULL) {
+ *ppolicy = talloc_steal(memctx, state->ppolicy);
+ }
switch (state->result) {
case LDAP_SUCCESS:
*result = SDAP_AUTH_SUCCESS;
@@ -1078,7 +1111,7 @@ static void sdap_cli_auth_done(struct tevent_req *subreq)
enum sdap_result result;
int ret;
- ret = sdap_auth_recv(subreq, &result);
+ ret = sdap_auth_recv(subreq, NULL, &result, NULL);
talloc_zfree(subreq);
if (ret) {
tevent_req_error(req, ret);
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index 2ba6f15..07ed4e7 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -3,6 +3,7 @@
Sumit Bose <sbose@redhat.com>
Copyright (C) 2009 Red Hat
+ Copyright (C) 2010, rhafer@suse.de, Novell Inc.
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
@@ -436,6 +437,81 @@ static int user_info_offline_auth(pam_handle_t *pamh, size_t buflen,
return PAM_SUCCESS;
}
+static int user_info_grace_login(pam_handle_t *pamh,
+ size_t buflen,
+ uint8_t *buf)
+{
+ int ret;
+ uint32_t grace;
+ char user_msg[256];
+
+ if (buflen != 2* sizeof(uint32_t)) {
+ D(("User info response data has the wrong size"));
+ return PAM_BUF_ERR;
+ }
+ memcpy(&grace, buf + sizeof(uint32_t), sizeof(uint32_t));
+ ret = snprintf(user_msg, sizeof(user_msg),
+ _("Your password has expired. "
+ "You have %d grace login(s) remaining."),
+ grace);
+ if (ret < 0 || ret >= sizeof(user_msg)) {
+ D(("snprintf failed."));
+ return PAM_SYSTEM_ERR;
+ }
+ ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
+
+ if (ret != PAM_SUCCESS) {
+ D(("do_pam_conversation failed."));
+ return PAM_SYSTEM_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
+#define MINSEC 60
+#define HOURSEC (60*MINSEC)
+#define DAYSEC (24*HOURSEC)
+static int user_info_expire_warn(pam_handle_t *pamh,
+ size_t buflen,
+ uint8_t *buf)
+{
+ int ret;
+ uint32_t expire;
+ char user_msg[256];
+ const char* unit="second(s)";
+
+ if (buflen != 2* sizeof(uint32_t)) {
+ D(("User info response data has the wrong size"));
+ return PAM_BUF_ERR;
+ }
+ memcpy(&expire, buf + sizeof(uint32_t), sizeof(uint32_t));
+ if (expire >= DAYSEC) {
+ expire /= DAYSEC;
+ unit = "day(s)";
+ } else if (expire >= HOURSEC) {
+ expire /= HOURSEC;
+ unit = "hour(s)";
+ } else if (expire >= MINSEC) {
+ expire /= MINSEC;
+ unit = "minute(s)";
+ }
+
+ ret = snprintf(user_msg, sizeof(user_msg),
+ _("Your password will expire in %d %s."), expire, unit);
+ if (ret < 0 || ret >= sizeof(user_msg)) {
+ D(("snprintf failed."));
+ return PAM_SYSTEM_ERR;
+ }
+ ret = do_pam_conversation(pamh, PAM_TEXT_INFO, user_msg, NULL, NULL);
+
+ if (ret != PAM_SUCCESS) {
+ D(("do_pam_conversation failed."));
+ return PAM_SYSTEM_ERR;
+ }
+
+ return PAM_SUCCESS;
+}
+
static int user_info_offline_auth_delayed(pam_handle_t *pamh, size_t buflen,
uint8_t *buf)
{
@@ -563,6 +639,12 @@ static int eval_user_info_response(pam_handle_t *pamh, size_t buflen,
case SSS_PAM_USER_INFO_OFFLINE_AUTH:
ret = user_info_offline_auth(pamh, buflen, buf);
break;
+ case SSS_PAM_USER_INFO_GRACE_LOGIN:
+ ret = user_info_grace_login(pamh, buflen, buf);
+ break;
+ case SSS_PAM_USER_INFO_EXPIRE_WARN:
+ ret = user_info_expire_warn(pamh, buflen, buf);
+ break;
case SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED:
ret = user_info_offline_auth_delayed(pamh, buflen, buf);
break;
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index 2edd158..f387265 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -377,13 +377,22 @@ enum user_info_type {
* possible to change the password while
* the system is offline. This message
* is generated by the PAM responder. */
- SSS_PAM_USER_INFO_CHPASS_ERROR /**< Tell the user that a password change
- * failed and optionally give a reason.
- * @param Size of the message as unsigned
- * 32-bit integer value. A value of 0
- * indicates that no message is following.
- * @param String with the specified
- * length. */
+ SSS_PAM_USER_INFO_CHPASS_ERROR, /**< Tell the user that a password change
+ * failed and optionally give a reason.
+ * @param Size of the message as unsigned
+ * 32-bit integer value. A value of 0
+ * indicates that no message is following.
+ * @param String with the specified
+ * length. */
+ SSS_PAM_USER_INFO_GRACE_LOGIN, /**< Warn the user that the password is
+ * expired and inform about the remaining
+ * number of grace logins.
+ * @param The number of remaining grace
+ * logins as uint32_t */
+ SSS_PAM_USER_INFO_EXPIRE_WARN /**< Warn the user that the password will
+ * expire soon.
+ * @param Number of seconds before the user's
+ * password will expire. */
};
/**
* @}
--
1.7.0.2

View File

@ -0,0 +1,29 @@
From 840bb425fe0cb6f4904d5610ffd1fdfd9eed235d Mon Sep 17 00:00:00 2001
From: Ralf Haferkamp <rhafer@suse.de>
Date: Wed, 31 Mar 2010 10:40:13 +0200
Subject: [PATCH] ldap provider ld flags
The LDAP provider needs to be linked against libdhash
---
src/Makefile.am | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 6d46cda..6f14eee 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -717,9 +717,11 @@ libsss_ldap_la_SOURCES = \
util/sss_krb5.c
libsss_ldap_la_CFLAGS = \
$(AM_CFLAGS) \
+ $(DHASH_CFLAGS) \
$(LDAP_CFLAGS) \
$(KRB5_CFLAGS)
libsss_ldap_la_LIBADD = \
+ $(DHASH_LIBS) \
$(OPENLDAP_LIBS) \
$(KRB5_LIBS)
libsss_ldap_la_LDFLAGS = \
--
1.7.0.2

View File

@ -0,0 +1,29 @@
From b9090cb4d12147267a4fb1ad9bb74bb226bcbe34 Mon Sep 17 00:00:00 2001
From: Ralf Haferkamp <rhafer@suse.de>
Date: Wed, 31 Mar 2010 12:21:21 +0200
Subject: [PATCH] init script dependencies
---
src/sysv/SUSE/sssd | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/sysv/SUSE/sssd b/src/sysv/SUSE/sssd
index 2f98c21..262ecde 100644
--- a/src/sysv/SUSE/sssd
+++ b/src/sysv/SUSE/sssd
@@ -1,10 +1,10 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: sssd
-# Required-Start: $remote_fs $time
+# Required-Start: $network $remote_fs $time
# Should-Start: $syslog
# Should-Stop: $syslog
-# Required-Stop: $remote_fs
+# Required-Stop: $network $remote_fs $time
# Default-Start: 3 5
# Default-Stop: 0 1 2 4 6
# Short-Description: System Security Services Daemon
--
1.7.0.2

3
sssd-1.1.0.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6b7805445f2f04505c26186d112bf3c53f6fd0e374a7ded476bfc1185b7c13be
size 2838565

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3be81ad8a17c76f7a9269b7ddc14abd4f41d04db10f49a34771c300b6b6bfa82
size 2264583

View File

@ -1,32 +1,3 @@
-------------------------------------------------------------------
Fri Sep 3 13:17:48 UTC 2010 - rhafer@novell.com
- No dependencies on %{release}
-------------------------------------------------------------------
Mon Aug 30 12:57:47 UTC 2010 - rhafer@novell.com
- Updated to 1.3.1
* Fixes to the HBAC backend for obsolete or removed HBAC entries
* Improvements to log messages around TLS and GSSAPI for LDAP
* Support for building in environments using --as-needed LDFLAGS
* Vast performance improvement for initgroups on RFC2307 LDAP servers
* Long-running SSSD clients (e.g. GDM) will now reconnect properly to the
daemon if SSSD is restarted
* Rewrote the internal LDB cache API. As a synchronous API it is now faster
to access and easier to work with
* Eugene Indenbom contributed a sizeable amount of code to the LDAP provider
- We now handle failover situations much more reliably than we did
previously
- We also will now monitor the GSSAPI kerberos ticket and automatically
renew it when appropriate, instead of waiting for a connection to fail
* Support for netlink now allows us to more quickly detect situations
where we may have come online
* New option "dns_discovery_domain" allows better configuration for
using SRV records for failover
- New subpackages: libpath_utils1, libpath_utils-devel, libref_array1
and libref_array-devel
------------------------------------------------------------------- -------------------------------------------------------------------
Wed Mar 31 14:02:43 UTC 2010 - rhafer@novell.com Wed Mar 31 14:02:43 UTC 2010 - rhafer@novell.com

132
sssd.spec
View File

@ -18,20 +18,24 @@
Name: sssd Name: sssd
Version: 1.3.1 Version: 1.1.0
Release: 1 Release: 1
Group: System/Daemons Group: System/Daemons
Summary: System Security Services Daemon Summary: System Security Services Daemon
License: GPLv3+ and LGPLv3+ License: GPLv3+ and LGPLv3+
Url: https://fedorahosted.org/sssd/ Url: https://fedorahosted.org/sssd/
Source0: %{name}-%{version}.tar.bz2 Source0: %{name}-%{version}.tar.gz
Source1: baselibs.conf Source1: baselibs.conf
Patch1: 0001-Added-option-to-use-libcrypto-instead-of-NSS.patch
Patch2: 0002-Improvements-for-LDAP-Password-Policy-support.patch
Patch3: 0003-ldap-provider-ld-flags.patch
Patch4: 0004-init-script-dependencies.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRoot: %{_tmppath}/%{name}-%{version}-build
%define dhash_version 0.4.0 %define dhash_version 0.4.0
%define path_utils_version 0.2.0 %define path_utils_version 0.2.0
%define collection_version 0.5.0 %define collection_version 0.4.0
%define ini_config_version 0.6.0 %define ini_config_version 0.4.0
%define refarray_version 0.1.0 %define refarray_version 0.1.0
### Dependencies ### ### Dependencies ###
@ -50,21 +54,17 @@ BuildRequires: libtalloc-devel
BuildRequires: libtevent-devel BuildRequires: libtevent-devel
BuildRequires: libtdb-devel BuildRequires: libtdb-devel
BuildRequires: libldb-devel BuildRequires: libldb-devel
BuildRequires: libxslt
BuildRequires: libxml2
BuildRequires: libcares-devel
BuildRequires: libnl-devel
BuildRequires: dbus-1-devel BuildRequires: dbus-1-devel
BuildRequires: openldap2-devel BuildRequires: openldap2-devel
BuildRequires: pam-devel BuildRequires: pam-devel
BuildRequires: pkg-config BuildRequires: pkg-config
BuildRequires: pcre-devel BuildRequires: pcre-devel
BuildRequires: libxslt
BuildRequires: libxml2
BuildRequires: docbook-xsl-stylesheets BuildRequires: docbook-xsl-stylesheets
BuildRequires: krb5-devel BuildRequires: krb5-devel
BuildRequires: libcares-devel
BuildRequires: python-devel BuildRequires: python-devel
BuildRequires: bind-utils
BuildRequires: nscd
%description %description
Provides a set of daemons to manage access to remote directories and Provides a set of daemons to manage access to remote directories and
@ -126,14 +126,14 @@ License: LGPLv3+
A hash table which will dynamically resize to achieve optimal storage & access A hash table which will dynamically resize to achieve optimal storage & access
time properties time properties
%package -n libcollection2 %package -n libcollection1
Summary: Collection data-type for C Summary: Collection data-type for C
Group: Development/Libraries/C and C++ Group: Development/Libraries/C and C++
Version: %{collection_version} Version: %{collection_version}
Release: 1 Release: 1
License: LGPLv3+ License: LGPLv3+
%description -n libcollection2 %description -n libcollection1
A data-type to collect data in a heirarchical structure for easy iteration A data-type to collect data in a heirarchical structure for easy iteration
and serialization and serialization
@ -142,21 +142,21 @@ Summary: Development files for libcollection
Group: Development/Libraries/C and C++ Group: Development/Libraries/C and C++
Version: %{collection_version} Version: %{collection_version}
Release: 1 Release: 1
Requires: libcollection2 = %{collection_version} Requires: libcollection1 = %{collection_version}
License: LGPLv3+ License: LGPLv3+
%description -n libcollection-devel %description -n libcollection-devel
A data-type to collect data in a heirarchical structure for easy iteration A data-type to collect data in a heirarchical structure for easy iteration
and serialization and serialization
%package -n libini_config2 %package -n libini_config1
Summary: INI file parser for C Summary: INI file parser for C
Group: Development/Libraries/C and C++ Group: Development/Libraries/C and C++
Version: %{ini_config_version} Version: %{ini_config_version}
Release: 1 Release: 1
License: LGPLv3+ License: LGPLv3+
%description -n libini_config2 %description -n libini_config1
Library to process config files in INI format into a libcollection data Library to process config files in INI format into a libcollection data
structure structure
@ -165,57 +165,19 @@ Summary: Development files for libini_config
Group: Development/Libraries/C and C++ Group: Development/Libraries/C and C++
Version: %{ini_config_version} Version: %{ini_config_version}
Release: 1 Release: 1
Requires: libini_config2 = %{ini_config_version} Requires: libini_config1 = %{ini_config_version}
License: LGPLv3+ License: LGPLv3+
%description -n libini_config-devel %description -n libini_config-devel
Library to process config files in INI format into a libcollection data Library to process config files in INI format into a libcollection data
structure structure
%package -n libpath_utils1
Summary: Filesystem Path Utilities
Group: Development/Libraries/C and C++
Version: %{path_utils_version}
Release: 1
License: LGPLv3+
%description -n libpath_utils1
Utility functions to manipulate filesystem pathnames
%package -n libpath_utils-devel
Summary: Development files for libpath_utils
Group: Development/Libraries/C and C++
Version: %{path_utils_version}
Release: 1
Requires: libpath_utils1 = %{path_utils_version}
License: LGPLv3+
%description -n libpath_utils-devel
Utility functions to manipulate filesystem pathnames
%package -n libref_array1
Summary: A refcounted array for C
Group: Development/Libraries/C and C++
Version: %{refarray_version}
Release: 1
License: LGPLv3+
%description -n libref_array1
A dynamically-growing, reference-counted array
%package -n libref_array-devel
Summary: Development files for libref_array
Group: Development/Libraries/C and C++
Version: %{refarray_version}
Release: 1
Requires: libref_array1 = %{refarray_version}
License: LGPLv3+
%description -n libref_array-devel
A dynamically-growing, reference-counted array
%prep %prep
%setup -q %setup -q
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%build %build
autoreconf autoreconf
@ -229,8 +191,7 @@ export LDB_CFLAGS="-I/usr/include"
--enable-nsslibdir=/%{_lib} \ --enable-nsslibdir=/%{_lib} \
--enable-cryptp=yes \ --enable-cryptp=yes \
--with-ldb-lib-dir=%{_libdir}/ldb \ --with-ldb-lib-dir=%{_libdir}/ldb \
--with-selinux=no \ --with-selinux=no
--with-semanage=no
#make %{?_smp_mflags} #make %{?_smp_mflags}
make make
@ -268,6 +229,15 @@ rm $RPM_BUILD_ROOT/%{_libdir}/*.a
install -d $RPM_BUILD_ROOT/%{_docdir}/dhash install -d $RPM_BUILD_ROOT/%{_docdir}/dhash
mv $RPM_BUILD_ROOT/%{_datarootdir}/doc/dhash/* $RPM_BUILD_ROOT/%{_docdir}/dhash mv $RPM_BUILD_ROOT/%{_datarootdir}/doc/dhash/* $RPM_BUILD_ROOT/%{_docdir}/dhash
# remove currently unused libraries
rm -f \
$RPM_BUILD_ROOT/%{_libdir}/libref_array.* \
$RPM_BUILD_ROOT/%{_libdir}/pkgconfig/ref_array.pc \
$RPM_BUILD_ROOT/%{_prefix}/include/ref_array*.h \
$RPM_BUILD_ROOT/%{_libdir}/libpath_utils.* \
$RPM_BUILD_ROOT/%{_libdir}/pkgconfig/path_utils.pc \
$RPM_BUILD_ROOT/%{_prefix}/include/path_utils.h
%clean %clean
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
@ -285,21 +255,13 @@ rm -rf $RPM_BUILD_ROOT
%postun -n libdhash1 -p /sbin/ldconfig %postun -n libdhash1 -p /sbin/ldconfig
%post -n libcollection2 -p /sbin/ldconfig %post -n libcollection1 -p /sbin/ldconfig
%postun -n libcollection2 -p /sbin/ldconfig %postun -n libcollection1 -p /sbin/ldconfig
%post -n libini_config2 -p /sbin/ldconfig %post -n libini_config1 -p /sbin/ldconfig
%postun -n libini_config2 -p /sbin/ldconfig %postun -n libini_config1 -p /sbin/ldconfig
%post -n libpath_utils1 -p /sbin/ldconfig
%postun -n libpath_utils1 -p /sbin/ldconfig
%post -n libref_array1 -p /sbin/ldconfig
%postun -n libref_array1 -p /sbin/ldconfig
%files -f sss_daemon.lang %files -f sss_daemon.lang
%defattr(-,root,root,-) %defattr(-,root,root,-)
@ -373,7 +335,7 @@ rm -rf $RPM_BUILD_ROOT
%{_prefix}/include/dhash.h %{_prefix}/include/dhash.h
%doc %{_docdir}/dhash %doc %{_docdir}/dhash
%files -n libini_config2 %files -n libini_config1
%defattr(-,root,root,-) %defattr(-,root,root,-)
%{_libdir}/libini_config.so.* %{_libdir}/libini_config.so.*
@ -383,7 +345,7 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/pkgconfig/ini_config.pc %{_libdir}/pkgconfig/ini_config.pc
%{_prefix}/include/ini_config.h %{_prefix}/include/ini_config.h
%files -n libcollection2 %files -n libcollection1
%defattr(-,root,root,-) %defattr(-,root,root,-)
%{_libdir}/libcollection.so.* %{_libdir}/libcollection.so.*
@ -393,24 +355,4 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/pkgconfig/collection.pc %{_libdir}/pkgconfig/collection.pc
%{_prefix}/include/collection*.h %{_prefix}/include/collection*.h
%files -n libpath_utils1
%defattr(-,root,root,-)
%{_libdir}/libpath_utils.so.*
%files -n libpath_utils-devel
%defattr(-,root,root,-)
%{_libdir}/libpath_utils.so
%{_libdir}/pkgconfig/path_utils.pc
%{_prefix}/include/path_utils*.h
%files -n libref_array1
%defattr(-,root,root,-)
%{_libdir}/libref_array.so.*
%files -n libref_array-devel
%defattr(-,root,root,-)
%{_libdir}/libref_array.so
%{_libdir}/pkgconfig/ref_array.pc
%{_prefix}/include/ref_array*.h
%changelog %changelog