diff --git a/0001-Added-option-to-use-libcrypto-instead-of-NSS.patch b/0001-Added-option-to-use-libcrypto-instead-of-NSS.patch new file mode 100644 index 0000000..429adf0 --- /dev/null +++ b/0001-Added-option-to-use-libcrypto-instead-of-NSS.patch @@ -0,0 +1,451 @@ +From bf75a22ffc04dfa0387a1389750b0a1e6d3ac397 Mon Sep 17 00:00:00 2001 +From: Ralf Haferkamp +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 + +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 ++ * George McCollister ++ */ ++/* SHA512-based Unix crypt implementation. ++ Released into the Public Domain by Ulrich Drepper . */ ++ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "util/util.h" ++ ++#include ++#include ++ ++/* 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 + diff --git a/0002-Improvements-for-LDAP-Password-Policy-support.patch b/0002-Improvements-for-LDAP-Password-Policy-support.patch new file mode 100644 index 0000000..c155afe --- /dev/null +++ b/0002-Improvements-for-LDAP-Password-Policy-support.patch @@ -0,0 +1,415 @@ +From 536c01cf9a04573c2351542fe00973e1538014a5 Mon Sep 17 00:00:00 2001 +From: Ralf Haferkamp +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 + + 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 - 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 + + 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 + diff --git a/0003-ldap-provider-ld-flags.patch b/0003-ldap-provider-ld-flags.patch new file mode 100644 index 0000000..087ae76 --- /dev/null +++ b/0003-ldap-provider-ld-flags.patch @@ -0,0 +1,29 @@ +From 840bb425fe0cb6f4904d5610ffd1fdfd9eed235d Mon Sep 17 00:00:00 2001 +From: Ralf Haferkamp +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 + diff --git a/0004-init-script-dependencies.patch b/0004-init-script-dependencies.patch new file mode 100644 index 0000000..326a9c2 --- /dev/null +++ b/0004-init-script-dependencies.patch @@ -0,0 +1,29 @@ +From b9090cb4d12147267a4fb1ad9bb74bb226bcbe34 Mon Sep 17 00:00:00 2001 +From: Ralf Haferkamp +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 + diff --git a/sssd-1.1.0.tar.gz b/sssd-1.1.0.tar.gz new file mode 100644 index 0000000..8d8f9d4 --- /dev/null +++ b/sssd-1.1.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b7805445f2f04505c26186d112bf3c53f6fd0e374a7ded476bfc1185b7c13be +size 2838565 diff --git a/sssd-1.3.1.tar.bz2 b/sssd-1.3.1.tar.bz2 deleted file mode 100644 index 176823c..0000000 --- a/sssd-1.3.1.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3be81ad8a17c76f7a9269b7ddc14abd4f41d04db10f49a34771c300b6b6bfa82 -size 2264583 diff --git a/sssd.changes b/sssd.changes index 0af1b01..2cf79d0 100644 --- a/sssd.changes +++ b/sssd.changes @@ -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 diff --git a/sssd.spec b/sssd.spec index 9c4569d..e7725ef 100644 --- a/sssd.spec +++ b/sssd.spec @@ -18,20 +18,24 @@ Name: sssd -Version: 1.3.1 +Version: 1.1.0 Release: 1 Group: System/Daemons Summary: System Security Services Daemon License: GPLv3+ and LGPLv3+ Url: https://fedorahosted.org/sssd/ -Source0: %{name}-%{version}.tar.bz2 +Source0: %{name}-%{version}.tar.gz 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 %define dhash_version 0.4.0 %define path_utils_version 0.2.0 -%define collection_version 0.5.0 -%define ini_config_version 0.6.0 +%define collection_version 0.4.0 +%define ini_config_version 0.4.0 %define refarray_version 0.1.0 ### Dependencies ### @@ -50,21 +54,17 @@ BuildRequires: libtalloc-devel BuildRequires: libtevent-devel BuildRequires: libtdb-devel BuildRequires: libldb-devel -BuildRequires: libxslt -BuildRequires: libxml2 -BuildRequires: libcares-devel -BuildRequires: libnl-devel BuildRequires: dbus-1-devel BuildRequires: openldap2-devel BuildRequires: pam-devel BuildRequires: pkg-config BuildRequires: pcre-devel +BuildRequires: libxslt +BuildRequires: libxml2 BuildRequires: docbook-xsl-stylesheets BuildRequires: krb5-devel +BuildRequires: libcares-devel BuildRequires: python-devel -BuildRequires: bind-utils -BuildRequires: nscd - %description 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 time properties -%package -n libcollection2 +%package -n libcollection1 Summary: Collection data-type for C Group: Development/Libraries/C and C++ Version: %{collection_version} Release: 1 License: LGPLv3+ -%description -n libcollection2 +%description -n libcollection1 A data-type to collect data in a heirarchical structure for easy iteration and serialization @@ -142,21 +142,21 @@ Summary: Development files for libcollection Group: Development/Libraries/C and C++ Version: %{collection_version} Release: 1 -Requires: libcollection2 = %{collection_version} +Requires: libcollection1 = %{collection_version} License: LGPLv3+ %description -n libcollection-devel A data-type to collect data in a heirarchical structure for easy iteration and serialization -%package -n libini_config2 +%package -n libini_config1 Summary: INI file parser for C Group: Development/Libraries/C and C++ Version: %{ini_config_version} Release: 1 License: LGPLv3+ -%description -n libini_config2 +%description -n libini_config1 Library to process config files in INI format into a libcollection data structure @@ -165,57 +165,19 @@ Summary: Development files for libini_config Group: Development/Libraries/C and C++ Version: %{ini_config_version} Release: 1 -Requires: libini_config2 = %{ini_config_version} +Requires: libini_config1 = %{ini_config_version} License: LGPLv3+ %description -n libini_config-devel Library to process config files in INI format into a libcollection data 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 %setup -q +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 %build autoreconf @@ -229,8 +191,7 @@ export LDB_CFLAGS="-I/usr/include" --enable-nsslibdir=/%{_lib} \ --enable-cryptp=yes \ --with-ldb-lib-dir=%{_libdir}/ldb \ - --with-selinux=no \ - --with-semanage=no + --with-selinux=no #make %{?_smp_mflags} make @@ -268,6 +229,15 @@ rm $RPM_BUILD_ROOT/%{_libdir}/*.a install -d $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 rm -rf $RPM_BUILD_ROOT @@ -285,21 +255,13 @@ rm -rf $RPM_BUILD_ROOT %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 - -%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 +%postun -n libini_config1 -p /sbin/ldconfig %files -f sss_daemon.lang %defattr(-,root,root,-) @@ -373,7 +335,7 @@ rm -rf $RPM_BUILD_ROOT %{_prefix}/include/dhash.h %doc %{_docdir}/dhash -%files -n libini_config2 +%files -n libini_config1 %defattr(-,root,root,-) %{_libdir}/libini_config.so.* @@ -383,7 +345,7 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/pkgconfig/ini_config.pc %{_prefix}/include/ini_config.h -%files -n libcollection2 +%files -n libcollection1 %defattr(-,root,root,-) %{_libdir}/libcollection.so.* @@ -393,24 +355,4 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/pkgconfig/collection.pc %{_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