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