uncommitted - libpam-ccreds

Ready changes

Summary

Import uploads missing from VCS:

Diff

diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches
new file mode 100644
index 0000000..6857a8d
--- /dev/null
+++ b/.pc/.quilt_patches
@@ -0,0 +1 @@
+debian/patches
diff --git a/.pc/.quilt_series b/.pc/.quilt_series
new file mode 100644
index 0000000..c206706
--- /dev/null
+++ b/.pc/.quilt_series
@@ -0,0 +1 @@
+series
diff --git a/.pc/.version b/.pc/.version
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/.pc/.version
@@ -0,0 +1 @@
+2
diff --git a/.pc/PATCH-add-minimum_uid-option.patch/cc_pam.c b/.pc/PATCH-add-minimum_uid-option.patch/cc_pam.c
new file mode 100644
index 0000000..d096117
--- /dev/null
+++ b/.pc/PATCH-add-minimum_uid-option.patch/cc_pam.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2004 PADL Software Pty Ltd.
+ * All rights reserved.
+ * Use is subject to license.
+ */
+
+/*
+ * Glue between CC library and PAM framework
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <syslog.h>
+
+#include "cc_private.h"
+
+/* module flags */
+#define SM_FLAGS_USE_FIRST_PASS		0x01
+#define SM_FLAGS_TRY_FIRST_PASS		0x02
+#define SM_FLAGS_GLOBAL_SESSION		0x04
+#define SM_FLAGS_SERVICE_SPECIFIC	0x08
+
+/* module actions */
+#define SM_ACTION_VALIDATE_CCREDS	1
+#define SM_ACTION_STORE_CCREDS		2
+#define SM_ACTION_UPDATE_CCREDS		3
+
+PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,
+				   int flags, int argc, const char **argv);
+
+PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh,
+			      int flags, int argc, const char **argv);
+
+#if 0
+PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,
+				int flags, int argc, const char **argv);
+#endif
+
+static int _pam_sm_interact(pam_handle_t *pamh,
+			    int flags,
+			    const char **authtok)
+{
+	int rc;
+	char *p;
+	const struct pam_conv *conv;
+	struct pam_message msg[1];
+	const struct pam_message *pmsg;
+	struct pam_response *resp;
+
+	msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
+	msg[0].msg = (*authtok == NULL) ? "Password" : "Cached Password";
+
+	pmsg = &msg[0];
+
+	resp = NULL;
+
+	rc = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
+	if (rc != PAM_SUCCESS) {
+		return rc;
+	}
+
+	rc = conv->conv(1, &pmsg, &resp, conv->appdata_ptr);
+	if (rc != PAM_SUCCESS) {
+		return rc;
+	}
+
+	if (resp == NULL) {
+		return PAM_CONV_ERR;
+	}
+
+	if ((flags & PAM_DISALLOW_NULL_AUTHTOK) && resp[0].resp == NULL) {
+		free(resp);
+		return PAM_AUTH_ERR;
+	}
+
+	p = resp[0].resp;
+	resp[0].resp = NULL;
+
+	free(resp);
+
+	*authtok = p;
+
+	return pam_set_item(pamh, PAM_AUTHTOK, *authtok);
+}
+
+static int _pam_sm_display_message(pam_handle_t *pamh,
+				   const char *message,
+				   int style,
+				   int flags)
+{
+	int rc;
+	const struct pam_conv *conv;
+	struct pam_message msg;
+	const struct pam_message *pmsg;
+	struct pam_response *resp;
+
+	if (flags & PAM_SILENT) {
+		return PAM_SUCCESS;
+	}
+
+	rc = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
+	if (rc != PAM_SUCCESS) {
+		return rc;
+	}
+
+	msg.msg_style = style;
+	msg.msg = (char *)message;
+	resp = NULL;
+
+	pmsg = &msg;
+
+	rc = conv->conv(1, &pmsg, &resp, conv->appdata_ptr);
+
+	return rc;
+}
+
+static int _pam_sm_validate_cached_credentials(pam_handle_t *pamh,
+						   int flags, unsigned int sm_flags,
+						   const char *ccredsfile)
+{
+	int rc;
+	const char *authtok;
+	pam_cc_handle_t *pamcch = NULL;
+	int isRoot = (geteuid() == 0);
+
+	if (isRoot) {
+		rc = pam_cc_start_ext(pamh, ((sm_flags & SM_FLAGS_SERVICE_SPECIFIC) != 0),
+				      ccredsfile, CC_FLAGS_READ_ONLY, &pamcch);
+		if (rc != PAM_SUCCESS) {
+			return rc;
+		}
+	}
+
+	authtok = NULL;
+
+	switch (sm_flags & (SM_FLAGS_USE_FIRST_PASS | SM_FLAGS_TRY_FIRST_PASS)) {
+	case SM_FLAGS_USE_FIRST_PASS:
+	case SM_FLAGS_TRY_FIRST_PASS:
+		rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&authtok);
+		if (rc == PAM_SUCCESS) {
+			if (authtok == NULL)
+				authtok = "";
+		}
+		if ((sm_flags & SM_FLAGS_USE_FIRST_PASS) || (rc == PAM_SUCCESS))
+			break;
+	case 0:
+		rc = _pam_sm_interact(pamh, flags, &authtok);
+		if (rc != PAM_SUCCESS) {
+			break;
+		}
+
+		if (authtok == NULL)
+			authtok = "";
+
+		break;
+	default:
+		syslog(LOG_ERR, "pam_ccreds: internal error.");
+		rc = PAM_SERVICE_ERR;
+	}
+
+	if (rc == PAM_SUCCESS) {
+		if (isRoot)
+			rc = pam_cc_validate_credentials(pamcch, PAM_CC_TYPE_DEFAULT,
+							 authtok, strlen(authtok));
+		else
+			rc = pam_cc_run_helper_binary(pamh, CCREDS_VALIDATE, authtok,
+						      ((sm_flags & SM_FLAGS_SERVICE_SPECIFIC) != 0));
+	}
+
+	if (rc == PAM_SUCCESS) {
+		_pam_sm_display_message(pamh,
+					"You have been logged on using cached credentials.",
+					PAM_TEXT_INFO, flags);
+	}
+
+	pam_cc_end(&pamcch);
+
+	return rc;
+}
+
+static int _pam_sm_store_cached_credentials(pam_handle_t *pamh,
+					    int flags, unsigned int sm_flags,
+					    const char *ccredsfile)
+{
+	int rc;
+	const char *authtok;
+	pam_cc_handle_t *pamcch = NULL;
+	int isRoot = (geteuid() == 0);
+
+	if (isRoot) {
+		rc = pam_cc_start_ext(pamh, ((sm_flags & SM_FLAGS_SERVICE_SPECIFIC) != 0),
+				      ccredsfile, 0, &pamcch);
+		if (rc != PAM_SUCCESS) {
+			return rc;
+		}
+	}
+
+	authtok = NULL;
+
+	rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&authtok);
+	if (rc != PAM_SUCCESS) {
+		pam_cc_end(&pamcch);
+		return rc;
+	}
+
+	if (authtok == NULL)
+		authtok = "";
+
+	if (isRoot) 
+		rc = pam_cc_store_credentials(pamcch, PAM_CC_TYPE_DEFAULT,
+					      authtok, strlen(authtok));
+	else
+		/* Unable to perform when not root; just return success. */
+		rc = PAM_SUCCESS;
+
+	pam_cc_end(&pamcch);
+
+	return rc;
+}
+
+static int _pam_sm_update_cached_credentials(pam_handle_t *pamh,
+					     int flags, unsigned int sm_flags,
+					     const char *ccredsfile)
+{
+	int rc;
+	const char *authtok;
+	pam_cc_handle_t *pamcch = NULL;
+	int isRoot = (geteuid() == 0);
+
+	authtok = NULL;
+
+	/*
+	 * FIXME: the logic of this function is a little difficult.
+	 * It may be wiser to provide an alternate implementation of the
+	 * pam_cc_db_* interface.
+	 */
+        if (isRoot) {
+		rc = pam_cc_start_ext(pamh, ((sm_flags & SM_FLAGS_SERVICE_SPECIFIC) != 0),
+				      ccredsfile, 0, &pamcch);
+		if (rc != PAM_SUCCESS) {
+			return rc;
+		}
+	}
+
+	rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&authtok);
+	if (rc == PAM_SUCCESS) {
+		if (authtok == NULL)
+			authtok = "";
+
+		if (isRoot)
+			rc = pam_cc_delete_credentials(pamcch, PAM_CC_TYPE_DEFAULT,
+						       authtok, strlen(authtok));
+		else
+			/* Unable to perform when not root; just return success. */
+			rc = PAM_SUCCESS;
+	}
+
+	pam_cc_end(&pamcch);
+
+	return rc;
+}
+
+static int _pam_sm_parse_action(const char *action, unsigned int *val)
+{
+	if (strcmp(action, "validate") == 0)
+		*val = SM_ACTION_VALIDATE_CCREDS;
+	else if (strcmp(action, "store") == 0)
+		*val = SM_ACTION_STORE_CCREDS;
+	else if (strcmp(action, "update") == 0)
+		*val = SM_ACTION_UPDATE_CCREDS;
+	else
+		return -1;
+
+	return 0;
+}
+
+PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,
+				   int flags, int argc, const char **argv)
+{
+	int i;
+	int rc;
+	unsigned int sm_flags = 0, sm_action = 0;
+	const char *ccredsfile = NULL;
+	const char *action = NULL;
+	int (*selector)(pam_handle_t *, int, unsigned int, const char *);
+
+	for (i = 0; i < argc; i++) {
+		if (strcmp(argv[i], "use_first_pass") == 0)
+			sm_flags |= SM_FLAGS_USE_FIRST_PASS;
+		else if (strcmp(argv[i], "try_first_pass") == 0)
+			sm_flags |= SM_FLAGS_TRY_FIRST_PASS;
+		else if (strcmp(argv[i], "service_specific") == 0)
+			sm_flags |= SM_FLAGS_SERVICE_SPECIFIC;
+		else if (strncmp(argv[i], "ccredsfile=", sizeof("ccredsfile=") - 1) == 0)
+			ccredsfile = argv[i] + sizeof("ccredsfile=") - 1;
+		else if (strncmp(argv[i], "action=", sizeof("action=") - 1) == 0)
+			action = argv[i] + sizeof("action=") - 1;
+		else
+			syslog(LOG_ERR, "pam_ccreds: illegal option %s", argv[i]);
+	}
+
+	if ((sm_flags & (SM_FLAGS_USE_FIRST_PASS | SM_FLAGS_TRY_FIRST_PASS))
+	    == (SM_FLAGS_USE_FIRST_PASS | SM_FLAGS_TRY_FIRST_PASS)) {
+		syslog(LOG_ERR, "pam_ccreds: both use_first_pass and try_first_pass given");
+		return PAM_SERVICE_ERR;
+	}
+
+	if (action == NULL) {
+		syslog(LOG_ERR, "pam_ccreds: configuration file did not "
+		       "specify any action");
+	} else if (_pam_sm_parse_action(action, &sm_action) != 0) {
+		syslog(LOG_ERR, "pam_ccreds: invalid action \"%s\"", action);
+	}
+
+	switch (sm_action) {
+	case SM_ACTION_VALIDATE_CCREDS:
+		selector = _pam_sm_validate_cached_credentials;
+		break;
+	case SM_ACTION_STORE_CCREDS:
+		selector = _pam_sm_store_cached_credentials;
+		break;
+	case SM_ACTION_UPDATE_CCREDS:
+		selector = _pam_sm_update_cached_credentials;
+		break;
+	default:
+		syslog(LOG_ERR, "pam_ccreds: invalid action %d", sm_action);
+		return PAM_SERVICE_ERR;
+	}
+
+	rc = (*selector)(pamh, flags, sm_flags, ccredsfile);
+
+	return rc;
+}
+
+/*
+ * Although it is tempting to use the setcred interface to
+ * cache the credentials, this would not be as useful as
+ * it initially sounds. Why is left as an exercise to the
+ * reader. :-)
+ */
+PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh,
+			      int flags, int argc, const char **argv)
+{
+	return PAM_SUCCESS;
+}
+
+#if 0
+/*
+ * Presently we do not cache whether a user was allowed to
+ * logon. We need to think about this, but it is difficult
+ * to do reliably as logon authorization may be dependent
+ * on things (time of day, for example) that one cannot
+ * introspect using the PAM API. We may thus lockout a 
+ * user who should otherwise be able to logon. Suggest that
+ * this be configured as a matter of policy (i.e. in
+ * pam.conf)
+ */
+PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,
+				int flags, int argc, const char **argv)
+{
+	return PAM_SUCCESS;
+}
+#endif
+
diff --git a/.pc/PATCH-make-sure-we-don-t-overflow-the-data-buffer.patch/cc_db.c b/.pc/PATCH-make-sure-we-don-t-overflow-the-data-buffer.patch/cc_db.c
new file mode 100644
index 0000000..c0e0488
--- /dev/null
+++ b/.pc/PATCH-make-sure-we-don-t-overflow-the-data-buffer.patch/cc_db.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2004 PADL Software Pty Ltd.
+ * All rights reserved.
+ * Use is subject to license.
+ */
+
+/*
+ * Database library wrappers
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+
+#include <sys/file.h>
+
+#ifdef HAVE_DB_H
+#include <db.h>
+#endif
+
+#include "cc_private.h"
+
+static int _pam_cc_db_lock(void *_db, int operation);
+static int _pam_cc_db_sync(void *_db);
+
+#if DB_VERSION_MAJOR <= 2
+#define USE_FLOCK	1
+#else
+/* XXX how do we enable locking here? */
+#define USE_FLOCK	1
+#endif
+
+#ifndef DB_NOTFOUND
+#define DB_NOTFOUND	1
+#endif
+
+/* Open an underlying datastore */
+int pam_cc_db_open(const char *filename, unsigned int flags,
+		   int mode, void **db_p)
+{
+	DB *db;
+	unsigned int db_flags = 0;
+
+#if DB_VERSION_MAJOR > 2
+	int rc;
+
+	if (flags & CC_DB_FLAGS_WRITE) {
+		db_flags |= DB_CREATE;
+	}
+	if (flags & CC_DB_FLAGS_READ) {
+		db_flags |= DB_RDONLY;
+	}
+
+	rc = db_create(&db, NULL, 0);
+	if (rc != 0) {
+		errno = rc;
+		return PAM_SERVICE_ERR;
+	}
+
+#if (DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0)
+	rc = db->open(db, NULL, filename, NULL,
+		      DB_BTREE, db_flags, mode);
+#else
+	rc = db->open(db, filename, NULL,
+		      DB_BTREE, db_flags, mode);
+#endif
+
+	if (rc != 0) {
+		db->close(db, 0);
+		errno = rc;
+		return PAM_SERVICE_ERR;
+	}
+
+#elif DB_VERSION_MAJOR == 2
+	int rc;
+
+	if (flags & CC_DB_FLAGS_WRITE) {
+		db_flags |= DB_CREATE;
+	}
+	if (flags & CC_DB_FLAGS_READ) {
+		db_flags |= DB_RDONLY;
+	}
+
+	rc = db_open(filename, DB_BTREE, db_flags, mode, NULL, NULL, &db);
+	if (rc != 0) {
+		errno = rc;
+		return PAM_SERVICE_ERR;
+	}
+#else
+	if (flags & CC_DB_FLAGS_WRITE) {
+		db_flags |= O_CREAT;
+	}
+	if (flags & CC_DB_FLAGS_READ) {
+		db_flags |= O_RDONLY;
+	}
+	db = dbopen(filename, db_flags, mode, DB_BTREE, NULL);
+	if (db == NULL) {
+		return PAM_SERVICE_ERR;
+	}
+#endif /* DB_VERSION_MAJOR > 2 */
+
+	*db_p = (void *)db;
+
+	return PAM_SUCCESS;
+}
+
+/* Write to underlying datastore */  
+int pam_cc_db_put(void *_db, const char *keyname, size_t keylength,
+		  const char *data, size_t size)
+{
+	DB *db = (DB *)_db;
+	DBT key;
+	DBT val;
+	int rc;
+
+	memset(&key, 0, sizeof(key));
+	key.data = (char *)keyname;
+	key.size = keylength;
+
+	memset(&val, 0, sizeof(val));
+	val.data = (char *)data;
+	val.size = size;
+
+#if USE_FLOCK
+	rc = _pam_cc_db_lock(db, LOCK_EX);
+	if (rc != PAM_SUCCESS) {
+		return rc;
+	}
+#endif
+
+	rc = db->put(db,
+#if DB_VERSION_MAJOR >= 2
+		NULL,
+#endif
+		&key, &val, 0);
+	if (rc == 0) {
+		rc = _pam_cc_db_sync(db);
+	} else {
+		fprintf(stderr, "%s\n", strerror(rc));
+#if DB_VERSION_MAJOR >= 2
+		errno = rc;
+#endif
+		rc = PAM_SERVICE_ERR;
+	}
+
+#if USE_FLOCK
+	_pam_cc_db_lock(db, LOCK_UN);
+#endif
+
+	return rc;
+}
+
+/* Read from underlying datastore */
+int pam_cc_db_get(void *_db, const char *keyname, size_t keylength,
+		  char *data, size_t *size)
+{
+	DB *db = (DB *)_db;
+	DBT key;
+	DBT val;
+	int rc;
+
+	memset(&key, 0, sizeof(key));
+	key.data = (char *)keyname;
+	key.size = keylength;
+
+	memset(&val, 0, sizeof(val));
+
+#if USE_FLOCK
+	rc = _pam_cc_db_lock(db, LOCK_SH);
+	if (rc != PAM_SUCCESS) {
+		return rc;
+	}
+#endif
+
+	rc = db->get(db,
+#if DB_VERSION_MAJOR >= 2
+		NULL,
+#endif
+		&key, &val, 0);
+
+#if USE_FLOCK
+	_pam_cc_db_lock(db, LOCK_UN);
+#endif
+
+	if (rc != 0) {
+#if DB_VERSION_MAJOR >= 2
+		if (rc != DB_NOTFOUND)
+			errno = rc;
+#endif
+		return (rc == DB_NOTFOUND) ? PAM_AUTHINFO_UNAVAIL : PAM_SERVICE_ERR;
+	}
+
+	if (val.size < *size) {
+		return PAM_BUF_ERR;
+	}
+
+	memcpy(data, val.data, val.size);
+	*size = val.size;
+
+	return PAM_SUCCESS;
+}
+
+int pam_cc_db_delete(void *_db, const char *keyname, size_t keylength)
+{
+	DB *db = (DB *)_db;
+	DBT key;
+	int rc;
+
+	memset(&key, 0, sizeof(key));
+	key.data = (char *)keyname;
+	key.size = keylength;
+
+#if USE_FLOCK
+	rc = _pam_cc_db_lock(db, LOCK_EX);
+	if (rc != PAM_SUCCESS) {
+		return rc;
+	}
+#endif
+
+	rc = db->del(db,
+#if DB_VERSION_MAJOR >= 2
+		NULL,
+#endif
+		&key, 0);
+	if (rc == 0) {
+		rc = _pam_cc_db_sync(db);
+	} else {
+#if DB_VERSION_MAJOR >= 2
+		if (rc != DB_NOTFOUND)
+			errno = rc;
+#endif
+		return (rc == DB_NOTFOUND) ? PAM_AUTHINFO_UNAVAIL : PAM_SERVICE_ERR;
+	}
+
+#if USE_FLOCK
+	_pam_cc_db_lock(db, LOCK_UN);
+#endif
+
+	return rc;
+}
+
+/* Close underlying datastore */
+int pam_cc_db_close(void **db_p)
+{
+	DB *db;
+
+	if (*db_p != NULL) {
+		db = *db_p;
+
+		if (db != NULL) {
+#if DB_VERSION_MAJOR >= 2
+			db->close(db, 0);
+#else
+			db->close(db);
+#endif /* DB_VERSION_MAJOR > 2 */
+		}
+
+		*db_p = NULL;
+	}
+
+	return PAM_SUCCESS;
+}
+
+static int _pam_cc_db_lock(void *_db, int operation)
+{
+	DB *db = (DB *)_db;
+	int fd;
+
+#if DB_VERSION_MAJOR >= 2
+	int rc;
+
+	rc = db->fd(db, &fd);
+	if (rc != 0) {
+		return PAM_SERVICE_ERR;
+	}
+#else
+	fd = db->fd(db);
+#endif /* DB_VERSION_MAJOR >= 2 */
+	if (fd < 0) {
+		return PAM_SERVICE_ERR;
+	}
+
+	if (flock(fd, operation) != 0) {
+		return PAM_AUTHTOK_LOCK_BUSY;
+	}
+
+	return PAM_SUCCESS;
+}
+
+static int _pam_cc_db_sync(void *_db)
+{
+	DB *db = (DB *)_db;
+	int rc;
+
+	rc = db->sync(db, 0);
+
+	return (rc == 0) ? PAM_SUCCESS : PAM_AUTHINFO_UNAVAIL;	
+}
+
+int pam_cc_db_seq(void *_db, void **cookie,
+		  const char **key_p, size_t *keylength_p,
+		  const char **data_p, size_t *datalength_p)
+{
+	DB *db = (DB *)_db;
+	DBT key;
+	DBT val;
+	int rc;
+#if DB_VERSION_MAJOR >= 2
+	DBC *cursor = (DBC *)*cookie;
+	int first = 0;
+#endif
+
+	memset(&key, 0, sizeof(key));
+	memset(&val, 0, sizeof(val));
+
+#if DB_VERSION_MAJOR < 2
+	rc = db->seq(db, &key, &val, (*cookie == NULL ? R_FIRST : R_NEXT));
+	if (*cookie == NULL) {
+		*cookie = (void *)1;
+	}
+#else
+	if (cursor == NULL) {
+# if DB_VERSION_MAJOR > 2 || (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 5)
+		rc = db->cursor(db, NULL, &cursor, 0);
+# else
+		rc = db->cursor(db, NULL, &cursor);
+# endif
+		if (rc != 0) {
+			errno = rc;
+			return PAM_SERVICE_ERR;
+		}
+
+		*cookie = cursor;
+		first++;
+	}
+
+	rc = cursor->c_get(cursor, &key, &val,
+			   first ? DB_FIRST : DB_NEXT);
+#endif /* DB_VERSION_MAJOR <= 2 */
+
+	switch (rc) {
+	case DB_NOTFOUND:
+		rc = PAM_SUCCESS;
+		break;
+	case 0:
+		rc = PAM_INCOMPLETE;
+		break;
+	default:
+		errno = rc;
+		rc = PAM_SERVICE_ERR;
+		return rc;
+		break;
+	}
+
+	*key_p = key.data;
+	*keylength_p = key.size;
+
+	*data_p = val.data;
+	*datalength_p = val.size;
+
+	return rc;
+}
+
diff --git a/.pc/applied-patches b/.pc/applied-patches
new file mode 100644
index 0000000..28ce340
--- /dev/null
+++ b/.pc/applied-patches
@@ -0,0 +1,2 @@
+PATCH-make-sure-we-don-t-overflow-the-data-buffer.patch
+PATCH-add-minimum_uid-option.patch
diff --git a/cc_db.c b/cc_db.c
index c0e0488..9371c4d 100644
--- a/cc_db.c
+++ b/cc_db.c
@@ -199,7 +199,7 @@ int pam_cc_db_get(void *_db, const char *keyname, size_t keylength,
 		return (rc == DB_NOTFOUND) ? PAM_AUTHINFO_UNAVAIL : PAM_SERVICE_ERR;
 	}
 
-	if (val.size < *size) {
+	if (val.size > *size) {
 		return PAM_BUF_ERR;
 	}
 
diff --git a/cc_pam.c b/cc_pam.c
index d096117..56776aa 100644
--- a/cc_pam.c
+++ b/cc_pam.c
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <syslog.h>
+#include <pwd.h>
 
 #include "cc_private.h"
 
@@ -45,6 +46,30 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,
 				int flags, int argc, const char **argv);
 #endif
 
+
+/*
+ * Given the PAM arguments and the user we're authenticating, see if we should
+ * ignore that user because they're root or have a low-numbered UID and we
+ * were configured to ignore such users.  Returns true if we should ignore
+ * them, false otherwise.
+ */
+static int
+_pamcc_should_ignore(const char *username, int minimum_uid)
+{
+	struct passwd *pwd;
+
+	if (minimum_uid > 0) {
+		pwd = getpwnam(username);
+		if (pwd != NULL && pwd->pw_uid < (unsigned long) minimum_uid) {
+			syslog(LOG_DEBUG, "ignoring low-UID user (%lu < %d)",
+				(unsigned long) pwd->pw_uid, minimum_uid);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
 static int _pam_sm_interact(pam_handle_t *pamh,
 			    int flags,
 			    const char **authtok)
@@ -291,7 +316,9 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,
 	unsigned int sm_flags = 0, sm_action = 0;
 	const char *ccredsfile = NULL;
 	const char *action = NULL;
+	const char *name = NULL;
 	int (*selector)(pam_handle_t *, int, unsigned int, const char *);
+	int minimum_uid = 0;
 
 	for (i = 0; i < argc; i++) {
 		if (strcmp(argv[i], "use_first_pass") == 0)
@@ -300,6 +327,8 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,
 			sm_flags |= SM_FLAGS_TRY_FIRST_PASS;
 		else if (strcmp(argv[i], "service_specific") == 0)
 			sm_flags |= SM_FLAGS_SERVICE_SPECIFIC;
+		else if (strncmp(argv[i], "minimum_uid=", sizeof("minimum_uid=") - 1) == 0)
+			minimum_uid = atoi(argv[i] + sizeof("minimum_uid=") - 1);
 		else if (strncmp(argv[i], "ccredsfile=", sizeof("ccredsfile=") - 1) == 0)
 			ccredsfile = argv[i] + sizeof("ccredsfile=") - 1;
 		else if (strncmp(argv[i], "action=", sizeof("action=") - 1) == 0)
@@ -321,6 +350,16 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,
 		syslog(LOG_ERR, "pam_ccreds: invalid action \"%s\"", action);
 	}
 
+	rc = pam_get_user(pamh, &name, NULL);
+	if (rc != PAM_SUCCESS || name == NULL) {
+		if (rc == PAM_CONV_AGAIN)
+			return PAM_INCOMPLETE;
+		else
+			return PAM_SERVICE_ERR;
+	}
+	if (_pamcc_should_ignore(name, minimum_uid))
+		return PAM_USER_UNKNOWN;
+
 	switch (sm_action) {
 	case SM_ACTION_VALIDATE_CCREDS:
 		selector = _pam_sm_validate_cached_credentials;
diff --git a/debian/changelog b/debian/changelog
index 83ced79..63ab1af 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,32 @@
+libpam-ccreds (10-8) unstable; urgency=medium
+
+  [ Helmut Grohne ]
+  * [8b5fbf4] Fix build/host confusion in libdir (Closes: #923062)
+
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 26 Oct 2019 00:28:29 +0200
+
+libpam-ccreds (10-7) unstable; urgency=medium
+
+  [ Guido Günther ]
+  * [22bf358] d/control: Switch Vcs-* URLs to salsa
+  * [febd29f] Switch to dh compat level 11
+  * [a424f5d] d/control: Sort build-deps
+  * [9cf04e9] Switch from cdbs to dh
+  * [571b309] d/control: Bump standards version
+  * [66b06b2] d/watch: Use https URI
+  * [3a1c830] d/watch: Drop boilerplate
+  * [1c2f6d5] d/control: Switch priority to optional
+  * [e59a65c] Turn on hardening
+  * [4c6eff4] Add autopkgtest
+  * [271fc27] Add gbp.conf
+  * [140ed0c] Rediff patches dropping the patch numbers
+
+  [ Andreas Metzler ]
+  * [5059fef] B-d on libgcrypt20-dev instead of libgcrypt11-dev
+    (Closes: #864117)
+
+ -- Guido Günther <agx@sigxcpu.org>  Fri, 02 Nov 2018 12:52:36 +0100
+
 libpam-ccreds (10-6) unstable; urgency=low
 
   * [2baa623] We don't need automake nor autoconf to build.
diff --git a/debian/compat b/debian/compat
index 7f8f011..b4de394 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-7
+11
diff --git a/debian/control b/debian/control
index 6c70f42..a9e7dae 100644
--- a/debian/control
+++ b/debian/control
@@ -1,12 +1,16 @@
 Source: libpam-ccreds
 Section: admin
-Priority: extra
+Priority: optional
 Maintainer: Guido Günther <agx@sigxcpu.org>
-Build-Depends: debhelper (>= 7), autotools-dev, libgcrypt11-dev,  libpam0g-dev, libdb-dev, cdbs
-Standards-Version: 3.8.4
+Build-Depends:
+ debhelper (>= 11),
+ libdb-dev,
+ libgcrypt20-dev,
+ libpam0g-dev,
+Standards-Version: 4.2.1
 Homepage: http://www.padl.com/OSS/pam_ccreds.html
-Vcs-Browser: http://git.debian.org/?p=users/agx/libpam-ccreds.git
-Vcs-Git: git://git.debian.org/users/agx/libpam-ccreds.git
+Vcs-Browser: https://salsa.debian.org/agx/libpam-ccreds
+Vcs-Git: https://salsa.debian.org/agx/libpam-ccreds.git
 
 Package: libpam-ccreds
 Architecture: any
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 0000000..cb0c7b2
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,5 @@
+[pq]
+patch-numbers = False
+
+[dch]
+id-length = 7
diff --git a/debian/patches/0002-add-minimum_uid-option.patch b/debian/patches/PATCH-add-minimum_uid-option.patch
similarity index 93%
rename from debian/patches/0002-add-minimum_uid-option.patch
rename to debian/patches/PATCH-add-minimum_uid-option.patch
index 29ea676..4c5eac4 100644
--- a/debian/patches/0002-add-minimum_uid-option.patch
+++ b/debian/patches/PATCH-add-minimum_uid-option.patch
@@ -1,11 +1,11 @@
-From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx@sigxcpu.org>
+From: =?utf-8?q?Guido_G=C3=BCnther?= <agx@sigxcpu.org>
 Date: Thu, 13 May 2010 12:36:26 +0200
 Subject: [PATCH] add minimum_uid option
 
 Closes: #580037
 ---
- cc_pam.c |   39 +++++++++++++++++++++++++++++++++++++++
- 1 files changed, 39 insertions(+), 0 deletions(-)
+ cc_pam.c | 39 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
 
 diff --git a/cc_pam.c b/cc_pam.c
 index d096117..56776aa 100644
@@ -86,4 +86,3 @@ index d096117..56776aa 100644
  	switch (sm_action) {
  	case SM_ACTION_VALIDATE_CCREDS:
  		selector = _pam_sm_validate_cached_credentials;
--- 
diff --git a/debian/patches/0001-make-sure-we-don-t-overflow-the-data-buffer.patch b/debian/patches/PATCH-make-sure-we-don-t-overflow-the-data-buffer.patch
similarity index 86%
rename from debian/patches/0001-make-sure-we-don-t-overflow-the-data-buffer.patch
rename to debian/patches/PATCH-make-sure-we-don-t-overflow-the-data-buffer.patch
index 2f0a82c..c4dbd44 100644
--- a/debian/patches/0001-make-sure-we-don-t-overflow-the-data-buffer.patch
+++ b/debian/patches/PATCH-make-sure-we-don-t-overflow-the-data-buffer.patch
@@ -3,8 +3,8 @@ Date: Mon, 23 Mar 2009 10:46:44 +0100
 Subject: [PATCH] make sure we don't overflow the data buffer
 
 ---
- cc_db.c |    2 +-
- 1 files changed, 1 insertions(+), 1 deletions(-)
+ cc_db.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/cc_db.c b/cc_db.c
 index c0e0488..9371c4d 100644
@@ -19,4 +19,3 @@ index c0e0488..9371c4d 100644
  		return PAM_BUF_ERR;
  	}
  
--- 
diff --git a/debian/patches/series b/debian/patches/series
index 9ace237..28ce340 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,2 @@
-0001-make-sure-we-don-t-overflow-the-data-buffer.patch
-0002-add-minimum_uid-option.patch
+PATCH-make-sure-we-don-t-overflow-the-data-buffer.patch
+PATCH-add-minimum_uid-option.patch
diff --git a/debian/rules b/debian/rules
index d82692f..2edb8f9 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,21 +1,22 @@
 #!/usr/bin/make -f
 
-include /usr/share/cdbs/1/rules/debhelper.mk
-include /usr/share/cdbs/1/class/autotools.mk
-
-DEB_FIXPERMS_EXCLUDE=/sbin/ccreds_chkpwd
-
-DEB_CONFIGURE_EXTRA_FLAGS :=     \
-	--host=$(DEB_HOST_GNU_TYPE) 	\
-        --build=$(DEB_BUILD_GNU_TYPE)   \
-	--prefix=/usr			\
-	--mandir=\$${prefix}/share/man 	\
-	--infodir=\$${prefix}/share/info\
-	--sbindir=/sbin			\
-	--libdir=/lib			\
-	--enable-gcrypt
-
-binary-install/libpam-ccreds::
+include /usr/share/dpkg/architecture.mk
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+DEB_CONFIGURE_EXTRA_ARGS := \
+	--libdir=/lib/$(DEB_HOST_GNU_TYPE) \
+	--sbindir=/sbin \
+	--enable-gcrypt \
+	$(NULL)
+
+%:
+	dh $@
+
+override_dh_auto_configure:
+	dh_auto_configure -- $(DEB_CONFIGURE_EXTRA_ARGS)
+
+override_dh_auto_install:
+	dh_auto_install
 	chown root:root debian/libpam-ccreds/sbin/ccreds_chkpwd
 	chmod 4755 debian/libpam-ccreds/sbin/ccreds_chkpwd
 
@@ -24,4 +25,8 @@ binary-install/libpam-ccreds::
 		debian/libpam-ccreds/usr/share/pam-configs/ccreds-save
 	install -m 0644 debian/libpam-ccreds.pam-auth-update.ccreds-check \
 		debian/libpam-ccreds/usr/share/pam-configs/ccreds-check
+	rmdir debian/libpam-ccreds/lib/security
+
+override_dh_fixperms:
+	dh_fixperms -X/sbin/ccreds_chkpwd
 
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..ddc05da
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,4 @@
+Tests: smoke
+Depends: @
+Restrictions: allow-stderr
+
diff --git a/debian/tests/smoke b/debian/tests/smoke
new file mode 100755
index 0000000..3be4fd4
--- /dev/null
+++ b/debian/tests/smoke
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -e
+set -x
+
+TMPFILE=$(mktemp)
+
+cc_test -store any foo 1234 "${TMPFILE}"
+cc_test -store any bar 1234 "${TMPFILE}"
+cc_test -store any foo 12341234 "${TMPFILE}"
+cc_test -validate any foo 12341234 "${TMPFILE}"
+! cc_test -validate any foo 1234 "${TMPFILE}"
+
+cc_test -update any foo - "${TMPFILE}"
+cc_dump "${TMPFILE}" | grep " bar "
+cc_dump "${TMPFILE}"
diff --git a/debian/watch b/debian/watch
index cb203c1..ed5e1a6 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,9 +1,6 @@
-# Example watch control file for uscan
-# Rename this file to "watch" and then you can run the "uscan" command
-# to check for upstream updates and more.
 # See uscan(1) for format
 
 # Compulsory line, this is a version 3 file
 version=3
 
-http://www.padl.com/download/pam_ccreds-(\d+)\.tar\.gz
+https://www.padl.com/download/pam_ccreds-(\d+)\.tar\.gz

Run locally

More details

Full run details