SHA256
1
0
forked from pool/sssd

Accepting request 36465 from network:ldap

Copy from network:ldap/sssd based on submit request 36465 from user rhafer

OBS-URL: https://build.opensuse.org/request/show/36465
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/sssd?expand=0&rev=4
This commit is contained in:
OBS User autobuild 2010-04-01 16:01:35 +00:00 committed by Git OBS Bridge
parent f70f20f55b
commit eb55f90389
10 changed files with 1126 additions and 52 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

@ -1,24 +0,0 @@
From 6a3686dbd6593d1f832231dd3e07fcd03eb9a2e6 Mon Sep 17 00:00:00 2001
From: Ralf Haferkamp <rhafer@suse.de>
Date: Mon, 8 Mar 2010 14:42:06 +0100
Subject: [PATCH] by default use logfiles for debug messages
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/server/sysv/SUSE/sssd b/server/sysv/SUSE/sssd
index 34fd837..2f98c21 100644
--- a/server/sysv/SUSE/sssd
+++ b/server/sysv/SUSE/sssd
@@ -29,7 +29,7 @@ PID_FILE=/var/run/sssd.pid
case "$1" in
start)
echo -n "Starting $prog "
- /sbin/startproc $SSSD -D 2>/dev/null
+ /sbin/startproc $SSSD -f -D 2>/dev/null
rc_status -v
;;
--
1.6.4.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

4
baselibs.conf Normal file
View File

@ -0,0 +1,4 @@
sssd
supplements "packageand(sssd:pam-<targettype>)"
supplements "packageand(sssd:glibc-<targettype>)"
-/usr/lib(64)?/*

View File

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

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 +1,31 @@
-------------------------------------------------------------------
Wed Mar 31 14:02:43 UTC 2010 - rhafer@novell.com
- Package pam- and nss-Modules as baselibs
- cleaned up file list and dependencies
- fixed init script dependencies
-------------------------------------------------------------------
Wed Mar 31 07:57:25 UTC 2010 - rhafer@novell.com
- Updated to 1.1.0
* Support for IPv6
* Support for LDAP referrals
* Offline failed login counter
* Fix for the long-standing cache cleanup performance issues
* libini_config, libcollection, libdhash, libref_array and
libpath_utils are now built as shared libraries for general
consumption (libref_array and libpath_utils are currently not
packaged, as no component in sssd links against them)
* Users get feedback from PAM if they authenticated offline
* Native local backend now has a utility to show nested memberships
(sss_groupshow)
* New "simple" access provider for easy restriction of users
- Backported libcrypto support from master to avoid Mozilla NSS
dependency
- Backported password policy improvments for LDAP provider from
master
-------------------------------------------------------------------
Mon Mar 8 14:06:29 UTC 2010 - rhafer@novell.com

192
sssd.spec
View File

@ -1,5 +1,5 @@
#
# spec file for package sssd (Version 1.0.5)
# spec file for package sssd (Version 1.1.0)
#
# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
@ -18,18 +18,25 @@
Name: sssd
Version: 1.0.5
Release: 2
Version: 1.1.0
Release: 1
Group: System/Daemons
Summary: System Security Services Daemon
# The entire source code is GPLv3+ except replace/ which is LGPLv3+
License: GPLv3+ and LGPLv3+
Url: https://fedorahosted.org/sssd/
Source0: %{name}-%{version}.tar.gz
Patch0: 0001-by-default-use-logfiles-for-debug-messages.dif
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
### Patches ###
%define dhash_version 0.4.0
%define path_utils_version 0.2.0
%define collection_version 0.4.0
%define ini_config_version 0.4.0
%define refarray_version 0.1.0
### Dependencies ###
%define servicename sssd
@ -38,7 +45,6 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build
%define pipepath %{sssdstatedir}/pipes
### Build Dependencies ###
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libtool
@ -52,8 +58,6 @@ BuildRequires: dbus-1-devel
BuildRequires: openldap2-devel
BuildRequires: pam-devel
BuildRequires: pkg-config
BuildRequires: mozilla-nss-devel
BuildRequires: mozilla-nspr-devel
BuildRequires: pcre-devel
BuildRequires: libxslt
BuildRequires: libxml2
@ -99,11 +103,84 @@ Group: Development/Libraries/Python
Provide python module to access and manage configuration of the System
Security Services Daemon (sssd).
%package -n libdhash1
Summary: Dynamic hash table
Group: Development/Libraries/C and C++
Version: %{dhash_version}
Release: 1
License: LGPLv3+
%description -n libdhash1
A hash table which will dynamically resize to achieve optimal storage & access
time properties
%package -n libdhash-devel
Summary: Development files for libdhash
Group: Development/Libraries/C and C++
Version: %{dhash_version}
Release: 1
Requires: libdhash1 = %{dhash_version}
License: LGPLv3+
%description -n libdhash-devel
A hash table which will dynamically resize to achieve optimal storage & access
time properties
%package -n libcollection1
Summary: Collection data-type for C
Group: Development/Libraries/C and C++
Version: %{collection_version}
Release: 1
License: LGPLv3+
%description -n libcollection1
A data-type to collect data in a heirarchical structure for easy iteration
and serialization
%package -n libcollection-devel
Summary: Development files for libcollection
Group: Development/Libraries/C and C++
Version: %{collection_version}
Release: 1
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_config1
Summary: INI file parser for C
Group: Development/Libraries/C and C++
Version: %{ini_config_version}
Release: 1
License: LGPLv3+
%description -n libini_config1
Library to process config files in INI format into a libcollection data
structure
%package -n libini_config-devel
Summary: Development files for libini_config
Group: Development/Libraries/C and C++
Version: %{ini_config_version}
Release: 1
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
%prep
%setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%build
autoreconf
export LDB_LIBS="-lldb"
export LDB_CFLAGS="-I/usr/include"
%configure \
@ -112,6 +189,7 @@ export LDB_CFLAGS="-I/usr/include"
--with-pipe-path=%{pipepath} \
--with-init-dir=%{_initrddir} \
--enable-nsslibdir=/%{_lib} \
--enable-cryptp=yes \
--with-ldb-lib-dir=%{_libdir}/ldb \
--with-selinux=no
@ -124,41 +202,82 @@ rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
# Copy default sssd.conf file
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/sssd
install -m600 server/examples/sssd.conf $RPM_BUILD_ROOT%{_sysconfdir}/sssd/sssd.conf
install server/sysv/SUSE/sssd $RPM_BUILD_ROOT%{_sysconfdir}/init.d/sssd
install -d $RPM_BUILD_ROOT/%{_sysconfdir}/sssd
install -m600 src/examples/sssd.conf $RPM_BUILD_ROOT%{_sysconfdir}/sssd/sssd.conf
install src/sysv/SUSE/sssd $RPM_BUILD_ROOT%{_sysconfdir}/init.d/sssd
ln -sf ../../etc/init.d/sssd $RPM_BUILD_ROOT/usr/sbin/rcsssd
# Remove .la files created by libtool
rm -f \
$RPM_BUILD_ROOT/%{_lib}/libnss_sss.la \
$RPM_BUILD_ROOT/%{_lib}/security/pam_sss.la \
$RPM_BUILD_ROOT/%{_libdir}/*.la \
$RPM_BUILD_ROOT/%{_libdir}/ldb/memberof.la \
$RPM_BUILD_ROOT/%{_libdir}/python2.6/site-packages/pysss.la \
$RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_ldap.la \
$RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_proxy.la \
$RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_krb5.la \
$RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_ipa.la \
$RPM_BUILD_ROOT/%{_libdir}/sssd/libsss_simple.la \
$RPM_BUILD_ROOT/%{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.la
rm $RPM_BUILD_ROOT/%{_libdir}/*.a
%find_lang sss_daemon
%find_lang sss_client
cat sss_client.lang >> sss_daemon.lang
#%find_lang sss_client
#cat sss_client.lang >> sss_daemon.lang
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
%post -p /sbin/ldconfig
%preun
%stop_on_removal sssd
%postun
/sbin/ldconfig
%restart_on_update sssd
%insserv_cleanup
%post -n libdhash1 -p /sbin/ldconfig
%postun -n libdhash1 -p /sbin/ldconfig
%post -n libcollection1 -p /sbin/ldconfig
%postun -n libcollection1 -p /sbin/ldconfig
%post -n libini_config1 -p /sbin/ldconfig
%postun -n libini_config1 -p /sbin/ldconfig
%files -f sss_daemon.lang
%defattr(-,root,root,-)
%doc COPYING
%{_initrddir}/%{name}
%{_sbindir}/sssd
%{_sbindir}/rcsssd
%{_libexecdir}/%{servicename}/
%dir %{_libdir}/%{name}/
%dir %{_libdir}/%{name}
%dir %{_libexecdir}/%{name}
%{_libexecdir}/%{name}/sss*
%{_libexecdir}/%{name}/*_child
%{_libexecdir}/%{name}/upgrade_config.py
%{_libdir}/%{name}/libsss_krb5*
%{_libdir}/%{name}/libsss_ldap*
%{_libdir}/%{name}/libsss_proxy*
%{_libdir}/%{name}/libsss_simple*
%{_libdir}/ldb/memberof.so
%{_libdir}/krb5/plugins/libkrb5/*
%dir %{sssdstatedir}
@ -174,10 +293,12 @@ rm -rf $RPM_BUILD_ROOT
%config %{_sysconfdir}/sssd/sssd.api.d/sssd-ldap.conf
%config %{_sysconfdir}/sssd/sssd.api.d/sssd-local.conf
%config %{_sysconfdir}/sssd/sssd.api.d/sssd-proxy.conf
%config %{_sysconfdir}/sssd/sssd.api.d/sssd-simple.conf
/%{_lib}/libnss_sss.so.2
/%{_lib}/security/pam_sss.so
%{_mandir}/man5/sssd-krb5.*
%{_mandir}/man5/sssd-ldap.*
%{_mandir}/man5/sssd-simple.*
%{_mandir}/man5/sssd.conf.*
%files tools
@ -189,6 +310,7 @@ rm -rf $RPM_BUILD_ROOT
%{_sbindir}/sss_groupadd
%{_sbindir}/sss_groupdel
%{_sbindir}/sss_groupmod
%{_sbindir}/sss_groupshow
%files ipa-provider
%defattr(-,root,root,-)
@ -202,15 +324,35 @@ rm -rf $RPM_BUILD_ROOT
%{python_sitelib}/*.py*
%{python_sitelib}/*.egg-info
%post
/sbin/ldconfig
%files -n libdhash1
%defattr(-,root,root,-)
%{_libdir}/libdhash.so.*
%preun
%stop_on_removal sssd
%files -n libdhash-devel
%defattr(-,root,root,-)
%{_libdir}/libdhash.so
%{_libdir}/pkgconfig/dhash.pc
%{_prefix}/include/dhash.h
%doc %{_docdir}/dhash
%postun
/sbin/ldconfig
%restart_on_update sssd
%insserv_cleanup
%files -n libini_config1
%defattr(-,root,root,-)
%{_libdir}/libini_config.so.*
%files -n libini_config-devel
%defattr(-,root,root,-)
%{_libdir}/libini_config.so
%{_libdir}/pkgconfig/ini_config.pc
%{_prefix}/include/ini_config.h
%files -n libcollection1
%defattr(-,root,root,-)
%{_libdir}/libcollection.so.*
%files -n libcollection-devel
%defattr(-,root,root,-)
%{_libdir}/libcollection.so
%{_libdir}/pkgconfig/collection.pc
%{_prefix}/include/collection*.h
%changelog