summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--lib/base64.c20
-rw-r--r--lib/env.c66
-rw-r--r--lib/graypam.h50
-rw-r--r--lib/ldappass.c107
-rw-r--r--lib/mem.c81
-rw-r--r--lib/slist.c127
-rw-r--r--lib/transform.c244
-rw-r--r--pam_groupmember/pam_groupmember.c1
-rw-r--r--pam_innetgr/pam_innetgr.c1
-rw-r--r--pam_ldaphome/pam_ldaphome.c306
-rw-r--r--pam_log/pam_log.c48
-rw-r--r--pam_regex/pam_regex.c26
-rw-r--r--pam_sql/pam_mysql.c14
-rw-r--r--pam_sql/pam_pgsql.c18
-rw-r--r--pam_sql/pam_sql.c81
-rw-r--r--pam_sql/pam_sql.h5
-rw-r--r--pam_umotd/pam_umotd.c49
17 files changed, 788 insertions, 456 deletions
diff --git a/lib/base64.c b/lib/base64.c
index 85b974a..9d0191e 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -51,19 +51,25 @@ gray_base64_decode(gray_slist_t slist, const char *iptr, size_t isize)
}
}
/* I have a entire block of data 32 bits get the output
data. */
if (i == 4) {
- gray_slist_append_char(slist,
- (data[0] << 2) | ((data[1] & 0x30) >> 4));
- gray_slist_append_char(slist,
- ((data[1] & 0xf) << 4) | ((data[2] & 0x3c) >> 2));
- gray_slist_append_char(slist,
- ((data[2] & 0x3) << 6) | data[3]);
+ if (gray_slist_append_char(slist,
+ (data[0] << 2) | ((data[1] & 0x30) >> 4)) != 1)
+ return -1;
+ if (gray_slist_append_char(slist,
+ ((data[1] & 0xf) << 4) | ((data[2] & 0x3c) >> 2))
+ != 1)
+ return -1;
+ if (gray_slist_append_char(slist,
+ ((data[2] & 0x3) << 6) | data[3]) != 1)
+ return -1;
nbytes += 3 - pad;
- } else
+ } else {
+ errno = EILSEQ;
return -1;
+ }
i = 0;
}
return nbytes;
}
diff --git a/lib/env.c b/lib/env.c
index 83152e4..b1da177 100644
--- a/lib/env.c
+++ b/lib/env.c
@@ -91,34 +91,45 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap)
if (!fp) {
_pam_log(LOG_ERR, "cannot open configuration file `%s': %s",
file_name, strerror (errno));
return 1;
}
- while (p = fgets(buf, sizeof buf, fp)) {
+ while ((p = fgets(buf, sizeof buf, fp))) {
int len;
struct gray_env *env;
line++;
while (*p && isspace(*p))
p++;
len = strlen(p);
if (len == 0)
continue;
if (p[len-1] != '\n') {
- if (!slist)
+ if (!slist) {
slist = gray_slist_create();
- gray_slist_append(slist, p, len);
- while (p = fgets(buf, sizeof buf, fp)) {
+ if (!slist) {
+ rc = errno;
+ break;
+ }
+ }
+ if (gray_slist_append(slist, p, len) != len) {
+ rc = errno;
+ break;
+ }
+ while ((p = fgets(buf, sizeof buf, fp))) {
len = strlen(p);
gray_slist_append(slist, p, len);
if (p[len - 1] == '\n')
break;
}
- gray_slist_append_char(slist, 0);
- p = gray_slist_finish(slist);
+ if (gray_slist_append_char(slist, 0) != 1
+ || (p = gray_slist_finish(slist)) == NULL) {
+ rc = errno;
+ break;
+ }
len = strlen(p);
}
p[len-1] = 0;
len = gray_trim_ws(p);
@@ -126,16 +137,25 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap)
continue;
if (p[len-1] == '\\') {
int err = 0;
/* Collect continuation lines */
- if (!slist)
+ if (!slist) {
slist = gray_slist_create();
+ if (!slist) {
+ rc = errno;
+ break;
+ }
+ }
do {
- gray_slist_append(slist, p, len - 1);
+ if (gray_slist_append(slist, p, len - 1)
+ != len - 1) {
+ rc = errno;
+ break;
+ }
p = fgets (buf, sizeof buf, fp);
if (!p)
break;
line++;
len = strlen(p);
if (len == 0)
@@ -147,32 +167,39 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap)
err = 1;
break;
}
p[len-1] = 0;
len = gray_trim_ws(p);
} while (p[len-1] == '\\');
- if (len)
- gray_slist_append(slist, p, len);
- gray_slist_append_char(slist, 0);
- p = gray_slist_finish(slist);
+ if (rc)
+ break;
+ if (len) {
+ if (gray_slist_append(slist, p, len) != len) {
+ rc = errno;
+ break;
+ }
+ }
+ if (gray_slist_append_char(slist, 0) != 1
+ || (p = gray_slist_finish(slist)) == NULL) {
+ rc = errno;
+ break;
+ }
if (err)
continue;
}
env = malloc(sizeof *env);
if (!env) {
- _pam_log(LOG_EMERG, "not enough memory");
- rc = 1;
+ rc = errno;
break;
}
env->name = strdup(p);
if (!env->name) {
- _pam_log(LOG_EMERG, "not enough memory");
+ rc = errno;
free(env);
- rc = 1;
break;
}
for (p = env->name; *p && !isspace(*p); p++)
;
if (*p)
@@ -192,13 +219,18 @@ gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap)
env->next = config_env;
config_env = env;
}
gray_slist_free(&slist);
fclose(fp);
- *penv = config_env;
+ if (rc) {
+ _pam_log(LOG_EMERG, "%s", strerror(rc));
+ gray_env_free(config_env);
+ } else {
+ *penv = config_env;
+ }
return rc;
}
int
gray_env_read(const char *file_name, struct gray_env **penv)
{
diff --git a/lib/graypam.h b/lib/graypam.h
index 76dcd68..69c4909 100644
--- a/lib/graypam.h
+++ b/lib/graypam.h
@@ -81,61 +81,69 @@
else \
gray_wait_debug(0, __FILE__, line); \
} while (0)
extern jmp_buf gray_pam_jmp;
-#define gray_pam_init(retval) \
- if (setjmp(gray_pam_jmp)) \
- return retval; \
-
-void gray_raise(const char *fmt, ...);
-
-void *gray_malloc(size_t size);
-void *gray_zalloc(size_t size);
-void *gray_calloc(size_t count, size_t size);
-void *gray_realloc(void *ptr, size_t size);
void *gray_2nrealloc(void *ptr, size_t *pcount, size_t elsiz);
-char *gray_strdup(const char *str);
void gray_pam_delete(char *x);
void gray_cleanup_string(pam_handle_t *pamh, void *x, int error_status);
void gray_cleanup_regex(pam_handle_t *pamh, void *x, int error_status);
void gray_make_str(pam_handle_t *pamh, const char *str, const char *name,
char **ret);
-
typedef struct gray_slist *gray_slist_t;
-gray_slist_t gray_slist_create();
+gray_slist_t gray_slist_create(void);
+int gray_slist_err(gray_slist_t slist);
+void gray_slist_clrerr(gray_slist_t slist);
void gray_slist_clear(gray_slist_t slist);
void gray_slist_free(gray_slist_t *slist);
-void gray_slist_append(gray_slist_t slist, const char *str, size_t n);
-void gray_slist_append_char(gray_slist_t slist, char c);
+ssize_t gray_slist_append(gray_slist_t slist, const char *str, size_t n);
+ssize_t gray_slist_append_char(gray_slist_t slist, char c);
size_t gray_slist_size(gray_slist_t slist);
-size_t gray_slist_coalesce(gray_slist_t slist);
+ssize_t gray_slist_coalesce(gray_slist_t slist);
void *gray_slist_head(gray_slist_t slist, size_t *psize);
void *gray_slist_finish(gray_slist_t slist);
-void gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend,
- int len, int base);
-void gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp);
+int gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend,
+ int len, int base);
+int gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp);
void gray_log_init(int dont_open, const char *tag, int f);
void gray_pam_vlog(int err, const char *format, va_list args);
void gray_pam_log(int err, const char *format, ...);
void gray_pam_debug(const char *format, ...);
void gray_wait_debug(size_t interval, const char *file, size_t line);
#define _pam_vlog gray_pam_vlog
#define _pam_log gray_pam_log
#define _pam_debug gray_pam_debug
-
+
+static inline int
+errno_to_pam(int ec)
+{
+ switch (ec) {
+ case EILSEQ:
+ _pam_log(LOG_ERR, "malformed password hash");
+ return PAM_SERVICE_ERR;
+
+ case ENOMEM:
+ _pam_log(LOG_ERR, "%s", strerror(errno));
+ return PAM_BUF_ERR;
+
+ default:
+ break;
+ }
+ _pam_log(LOG_ERR, "%s", strerror(errno));
+ return PAM_SERVICE_ERR;
+}
int gray_transform_name_to_slist (gray_slist_t slist, char *input, char **output);
-void gray_set_transform_expr (const char *expr);
+int gray_set_transform_expr (const char *expr);
void gray_free_transform_expr (void);
int gray_converse(pam_handle_t *pamh, int nargs,
struct pam_message **message,
struct pam_response **response);
diff --git a/lib/ldappass.c b/lib/ldappass.c
index 968078c..247cf16 100644
--- a/lib/ldappass.c
+++ b/lib/ldappass.c
@@ -45,119 +45,168 @@ chk_crypt (const char *db_pass, const char *pass)
static int
chk_md5 (const char *db_pass, const char *pass)
{
unsigned char md5digest[16];
struct gpam_md5_ctx md5context;
- gray_slist_t slist = gray_slist_create ();
+ gray_slist_t slist;
ssize_t size;
char *p;
int rc;
+
+ slist = gray_slist_create ();
+ if (!slist)
+ return errno_to_pam(errno);
gpam_md5_init_ctx (&md5context);
gpam_md5_process_bytes (pass, strlen (pass), &md5context);
gpam_md5_finish_ctx (&md5context, md5digest);
size = gray_base64_decode(slist, db_pass, strlen (db_pass));
if (size != 16)
{
+ rc = errno_to_pam(errno);
gray_slist_free(&slist);
- return PAM_AUTH_ERR;
+ return rc;
}
p = gray_slist_finish(slist);
- rc = memcmp (md5digest, p, sizeof md5digest) == 0 ?
- PAM_SUCCESS : PAM_AUTH_ERR;
+ if (p)
+ {
+ rc = memcmp (md5digest, p, sizeof md5digest) == 0
+ ? PAM_SUCCESS
+ : PAM_AUTH_ERR;
+ }
+ else
+ {
+ rc = errno_to_pam(errno);
+ }
gray_slist_free(&slist);
return rc;
}
static int
chk_smd5 (const char *db_pass, const char *pass)
{
int rc;
unsigned char md5digest[16];
unsigned char *d1;
struct gpam_md5_ctx md5context;
- gray_slist_t slist = gray_slist_create();
+ gray_slist_t slist;
ssize_t size;
+ slist = gray_slist_create();
+ if (!slist)
+ return errno_to_pam(errno);
+
size = gray_base64_decode(slist, db_pass, strlen (db_pass));
if (size <= 16)
{
- _pam_log(LOG_ERR, "malformed SMD5 password: %s", db_pass);
+ rc = errno_to_pam(errno);
gray_slist_free(&slist);
- return PAM_AUTH_ERR;
+ return rc;
}
d1 = gray_slist_finish(slist);
-
- gpam_md5_init_ctx (&md5context);
- gpam_md5_process_bytes (pass, strlen (pass), &md5context);
- gpam_md5_process_bytes (d1 + 16, size - 16, &md5context);
- gpam_md5_finish_ctx (&md5context, md5digest);
+ if (d1)
+ {
+ gpam_md5_init_ctx (&md5context);
+ gpam_md5_process_bytes (pass, strlen (pass), &md5context);
+ gpam_md5_process_bytes (d1 + 16, size - 16, &md5context);
+ gpam_md5_finish_ctx (&md5context, md5digest);
- rc = memcmp (md5digest, d1, sizeof md5digest) == 0 ?
- PAM_SUCCESS : PAM_AUTH_ERR;
+ rc = memcmp (md5digest, d1, sizeof md5digest) == 0
+ ? PAM_SUCCESS
+ : PAM_AUTH_ERR;
+ }
+ else
+ {
+ rc = errno_to_pam(gray_slist_err(slist));
+ }
+
gray_slist_free(&slist);
return rc;
}
static int
chk_sha (const char *db_pass, const char *pass)
{
int rc;
unsigned char sha1digest[20];
unsigned char *d1;
struct gpam_sha1_ctx sha1context;
- gray_slist_t slist = gray_slist_create();
+ gray_slist_t slist;
ssize_t size;
-
+
+ slist = gray_slist_create();
+ if (!slist)
+ return errno_to_pam(errno);
+
gpam_sha1_init_ctx (&sha1context);
gpam_sha1_process_bytes (pass, strlen (pass), &sha1context);
gpam_sha1_finish_ctx (&sha1context, sha1digest);
size = gray_base64_decode(slist, db_pass, strlen (db_pass));
if (size != 20)
{
+ rc = errno_to_pam(errno);
gray_slist_free(&slist);
- return 1;
+ return rc;
}
d1 = gray_slist_finish(slist);
- rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0 ?
- PAM_SUCCESS : PAM_AUTH_ERR;
+ if (d1)
+ {
+ rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0
+ ? PAM_SUCCESS
+ : PAM_AUTH_ERR;
+ }
+ else
+ {
+ rc = errno_to_pam(errno);
+ }
gray_slist_free(&slist);
return rc;
}
static int
chk_ssha (const char *db_pass, const char *pass)
{
int rc;
unsigned char sha1digest[20];
unsigned char *d1;
struct gpam_sha1_ctx sha1context;
- gray_slist_t slist = gray_slist_create();
+ gray_slist_t slist;
ssize_t size;
+ slist = gray_slist_create();
+ if (!slist)
+ return errno_to_pam(errno);
+
size = gray_base64_decode(slist, db_pass, strlen (db_pass));
if (size <= 16)
{
- _pam_log (LOG_ERR, "malformed SSHA1 password: %s", db_pass);
+ rc = errno_to_pam(errno);
gray_slist_free(&slist);
- return 1;
+ return rc;
}
d1 = gray_slist_finish(slist);
-
- gpam_sha1_init_ctx (&sha1context);
- gpam_sha1_process_bytes (pass, strlen (pass), &sha1context);
- gpam_sha1_process_bytes (d1 + 20, size - 20, &sha1context);
- gpam_sha1_finish_ctx (&sha1context, sha1digest);
+ if (d1)
+ {
+ gpam_sha1_init_ctx (&sha1context);
+ gpam_sha1_process_bytes (pass, strlen (pass), &sha1context);
+ gpam_sha1_process_bytes (d1 + 20, size - 20, &sha1context);
+ gpam_sha1_finish_ctx (&sha1context, sha1digest);
- rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0 ?
- PAM_SUCCESS : PAM_AUTH_ERR;
+ rc = memcmp (sha1digest, d1, sizeof sha1digest) == 0
+ ? PAM_SUCCESS
+ : PAM_AUTH_ERR;
+ }
+ else
+ {
+ rc = errno_to_pam(errno);
+ }
gray_slist_free(&slist);
return rc;
}
static struct passwd_algo
{
diff --git a/lib/mem.c b/lib/mem.c
index fbe5f06..bcb0a89 100644
--- a/lib/mem.c
+++ b/lib/mem.c
@@ -13,87 +13,34 @@
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <graypam.h>
-jmp_buf gray_pam_jmp;
-
-void
-gray_raise(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- _pam_vlog(LOG_ERR, fmt, ap);
- va_end(ap);
- longjmp(gray_pam_jmp, 1);
-}
-
-void *
-gray_malloc(size_t size)
-{
- void *p = malloc(size);
- if (!p)
- gray_raise("Not enough memory");
- return p;
-}
-
-void *
-gray_zalloc(size_t size)
-{
- void *p = malloc(size);
- if (!p)
- gray_raise("Not enough memory");
- memset(p, 0, size);
- return p;
-}
-
-void *
-gray_calloc(size_t count, size_t size)
-{
- return gray_zalloc(count * size);
-}
-
-void *
-gray_realloc(void *ptr, size_t size)
-{
- ptr = realloc(ptr, size);
- if (!ptr)
- gray_raise("Not enough memory");
- return ptr;
-}
-
void *
gray_2nrealloc(void *ptr, size_t *pcount, size_t elsiz)
{
size_t count = *pcount;
if (!ptr) {
- if (!count)
- count = *pcount = 16;
- return gray_calloc(count, elsiz);
+ if (!count) {
+ count = 64 / elsiz;
+ count += !count;
+ }
+ } else {
+ if ((size_t)-1 / 2 / elsiz <= count) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ count += (count + 1) / 2;
}
- if ((size_t)-1 / 2 / elsiz <= count)
- gray_raise("Not enough memory");
- count *= 2;
- *pcount = count;
- return gray_realloc(ptr, count * elsiz);
-}
-
-
-char *
-gray_strdup(const char *str)
-{
- char *p;
-
- if (!str)
- return NULL;
- p = gray_malloc(strlen(str) + 1);
- return strcpy(p, str);
+ ptr = realloc(ptr, count * elsiz);
+ if (ptr)
+ *pcount = count;
+ return ptr;
}
-
void
gray_pam_delete(char *x)
{
PAM_OVERWRITE(x);
free(x);
diff --git a/lib/slist.c b/lib/slist.c
index b110350..46e516e 100644
--- a/lib/slist.c
+++ b/lib/slist.c
@@ -25,125 +25,161 @@ struct gray_slist_bucket {
size_t size;
};
struct gray_slist {
struct gray_slist_bucket *head, *tail;
struct gray_slist_bucket *free;
+ int ec; /* error code */
};
static struct gray_slist_bucket *
alloc_bucket(size_t size)
{
- struct gray_slist_bucket *p = gray_malloc(sizeof(*p) + size);
- p->buf = (char*)(p + 1);
- p->level = 0;
- p->size = size;
- p->next = NULL;
+ struct gray_slist_bucket *p = malloc(sizeof(*p) + size);
+ if (p) {
+ p->buf = (char*)(p + 1);
+ p->level = 0;
+ p->size = size;
+ p->next = NULL;
+ }
return p;
}
-static void
+static int
alloc_pool(gray_slist_t slist, size_t size)
{
struct gray_slist_bucket *p = alloc_bucket(GRAY_SLIST_BUCKET_SIZE);
+ if (!p) {
+ slist->ec = errno;
+ return 1;
+ }
if (slist->tail)
slist->tail->next = p;
else
slist->head = p;
slist->tail = p;
+ return 0;
}
-static size_t
+static ssize_t
copy_chars(gray_slist_t slist, const char *str, size_t n)
{
size_t rest;
-
- if (!slist->head || slist->tail->level == slist->tail->size)
- alloc_pool(slist, GRAY_SLIST_BUCKET_SIZE);
+ if (!slist->head || slist->tail->level == slist->tail->size) {
+ if (alloc_pool(slist, GRAY_SLIST_BUCKET_SIZE))
+ return -1;
+ }
rest = slist->tail->size - slist->tail->level;
if (n > rest)
n = rest;
memcpy(slist->tail->buf + slist->tail->level, str, n);
slist->tail->level += n;
return n;
}
gray_slist_t
-gray_slist_create()
+gray_slist_create(void)
{
- gray_slist_t slist = gray_malloc(sizeof(*slist));
- slist->head = slist->tail = slist->free = 0;
+ gray_slist_t slist = malloc(sizeof(*slist));
+ if (slist) {
+ slist->head = slist->tail = slist->free = 0;
+ slist->ec = 0;
+ }
return slist;
}
+int
+gray_slist_err(gray_slist_t slist)
+{
+ return slist->ec;
+}
+
+void
+gray_slist_clerr(gray_slist_t slist)
+{
+ slist->ec = 0;
+}
+
void
gray_slist_clear(gray_slist_t slist)
{
if (slist->tail) {
slist->tail->next = slist->free;
slist->free = slist->head;
slist->head = slist->tail = NULL;
}
+ gray_slist_clerr(slist);
}
void
gray_slist_free(gray_slist_t *slist)
{
- struct gray_slist_bucket *p;
if (*slist) {
+ struct gray_slist_bucket *p;
gray_slist_clear(*slist);
for (p = (*slist)->free; p; ) {
struct gray_slist_bucket *next = p->next;
free(p);
p = next;
}
}
free(*slist);
*slist = NULL;
}
-void
+ssize_t
gray_slist_append(gray_slist_t slist, const char *str, size_t n)
{
- const char *ptr = str;
- while (n) {
- size_t s = copy_chars(slist, ptr, n);
- ptr += s;
- n -= s;
+ ssize_t total;
+
+ if (slist->ec)
+ return -1;
+ total = 0;
+ while (total < n) {
+ ssize_t s = copy_chars(slist, str + total, n - total);
+ if (s == -1)
+ return -1;
+ total += s;
}
+ return total;
}
-void
+ssize_t
gray_slist_append_char(gray_slist_t slist, char c)
{
- gray_slist_append(slist, &c, 1);
+ return gray_slist_append(slist, &c, 1);
}
size_t
gray_slist_size(gray_slist_t slist)
{
size_t size = 0;
struct gray_slist_bucket *p;
for (p = slist->head; p; p = p->next)
size += p->level;
return size;
}
-size_t
+ssize_t
gray_slist_coalesce(gray_slist_t slist)
{
size_t size;
- if (slist->head && slist->head->next == NULL)
+ if (slist->ec)
+ return -1;
+ else if (slist->head && slist->head->next == NULL)
size = slist->head->level;
else {
size = gray_slist_size(slist);
- struct gray_slist_bucket *bucket = alloc_bucket(size);
- struct gray_slist_bucket *p;
+ struct gray_slist_bucket *bucket, *p;
+
+ bucket = alloc_bucket(size);
+ if (!bucket)
+ return -1;
for (p = slist->head; p; ) {
struct gray_slist_bucket *next = p->next;
memcpy(bucket->buf + bucket->level, p->buf, p->level);
bucket->level += p->level;
free(p);
@@ -162,29 +198,34 @@ gray_slist_head(gray_slist_t slist, size_t *psize)
return slist->head ? slist->head->buf : NULL;
}
void *
gray_slist_finish(gray_slist_t slist)
{
- gray_slist_coalesce(slist);
+ if (slist->ec)
+ return NULL;
+ if (gray_slist_coalesce(slist) == -1)
+ return NULL;
gray_slist_clear(slist);
return slist->free->buf;
}
#define to_num(c) \
(isdigit(c) ? c - '0' : (isxdigit(c) ? toupper(c) - 'A' + 10 : 255 ))
-void
+int
gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend,
int len, int base)
{
int i;
int val = 0;
char *start = text;
-
+
+ if (slist->ec)
+ return -1;
if (text[0] == '\\') {
text++;
if (base == 16)
text++;
}
@@ -193,20 +234,23 @@ gray_slist_grow_backslash_num(gray_slist_t slist, char *text, char **pend,
if (n > 127 || (n = to_num(n)) >= base)
break;
val = val*base + n;
}
if (i == 0) {
- gray_slist_append(slist, start, 1);
+ if (gray_slist_append(slist, start, 1) != 1)
+ return -1;
if (pend)
*pend = start + 1;
} else {
- gray_slist_append_char(slist, val);
+ if (gray_slist_append_char(slist, val) != 1)
+ return -1;
if (pend)
*pend = text + i;
}
+ return 0;
}
int
gray_decode_backslash(int c)
{
static char transtab[] = "a\ab\bf\fn\nr\rt\t";
@@ -216,25 +260,30 @@ gray_decode_backslash(int c)
if (*p == c)
return p[1];
}
return c;
}
-void
+int
gray_slist_grow_backslash(gray_slist_t slist, char *text, char **endp)
{
if (text[1] == '\\' || (unsigned char)text[1] > 127) {
- gray_slist_append_char(slist, text[1]);
+ if (gray_slist_append_char(slist, text[1]) != 1)
+ return -1;
text += 2;
- } else if (isdigit(text[1]))
- gray_slist_grow_backslash_num(slist, text, &text, 3, 8);
- else if (text[1] == 'x' || text[1] == 'X')
- gray_slist_grow_backslash_num(slist, text, &text, 2, 16);
- else {
+ } else if (isdigit(text[1])) {
+ if (gray_slist_grow_backslash_num(slist, text, &text, 3, 8))
+ return -1;
+ } else if (text[1] == 'x' || text[1] == 'X') {
+ if (gray_slist_grow_backslash_num(slist, text, &text, 2, 16))
+ return -1;
+ } else {
int c = gray_decode_backslash(text[1]);
- gray_slist_append_char(slist, c);
+ if (gray_slist_append_char(slist, c) != 1)
+ return -1;
text += 2;
}
*endp = text;
+ return 0;
}
diff --git a/lib/transform.c b/lib/transform.c
index 36972f0..c8ed54d 100644
--- a/lib/transform.c
+++ b/lib/transform.c
@@ -60,29 +60,48 @@ struct transform
{
struct transform *next;
enum transform_type transform_type;
unsigned match_number;
regex_t regex;
int has_regex;
+ int error;
/* Compiled replacement expression */
struct replace_segm *repl_head, *repl_tail;
size_t segm_count; /* Number of elements in the above list */
};
+static inline int
+transform_err(struct transform *tf)
+{
+ return tf->error;
+}
+
+static void
+transform_seterr (struct transform *tf, int ec)
+{
+ errno_to_pam (errno);
+ tf->error = ec;
+}
+
static struct transform *transform_head, *transform_tail;
+static char *case_ctl_buffer;
+static size_t case_ctl_bufsize;
static struct transform *
-new_transform ()
+new_transform (void)
{
- struct transform *p = gray_zalloc (sizeof *p);
- if (transform_tail)
- transform_tail->next = p;
- else
- transform_head = p;
- transform_tail = p;
+ struct transform *p = calloc (1, sizeof *p);
+ if (p)
+ {
+ if (transform_tail)
+ transform_tail->next = p;
+ else
+ transform_head = p;
+ transform_tail = p;
+ }
return p;
}
static void free_segment (struct replace_segm *segm);
static void
@@ -99,103 +118,144 @@ free_transform (struct transform *tr)
}
}
static struct replace_segm *
add_segment (struct transform *tf)
{
- struct replace_segm *segm = gray_malloc (sizeof *segm);
- segm->next = NULL;
- if (tf->repl_tail)
- tf->repl_tail->next = segm;
+ struct replace_segm *segm = malloc (sizeof *segm);
+ if (segm)
+ {
+ segm->next = NULL;
+ if (tf->repl_tail)
+ tf->repl_tail->next = segm;
+ else
+ tf->repl_head = segm;
+ tf->repl_tail = segm;
+ tf->segm_count++;
+ }
else
- tf->repl_head = segm;
- tf->repl_tail = segm;
- tf->segm_count++;
+ transform_seterr (tf, errno_to_pam (errno));
return segm;
}
static void
free_segment (struct replace_segm *segm)
{
if (segm->type == segm_literal)
free (segm->v.literal.ptr);
free (segm);
}
static void
-add_literal_segment (struct transform *tf, char *str, char *end)
+add_literal_segment (struct transform *tf, char const *str, char const *end)
{
size_t len = end - str;
if (len)
{
struct replace_segm *segm = add_segment (tf);
- segm->type = segm_literal;
- segm->v.literal.ptr = gray_malloc (len + 1);
- memcpy (segm->v.literal.ptr, str, len);
- segm->v.literal.ptr[len] = 0;
- segm->v.literal.size = len;
+ if (segm)
+ {
+ segm->type = segm_literal;
+ segm->v.literal.ptr = malloc (len + 1);
+ if (segm->v.literal.ptr)
+ {
+ memcpy (segm->v.literal.ptr, str, len);
+ segm->v.literal.ptr[len] = 0;
+ segm->v.literal.size = len;
+ }
+ else
+ transform_seterr (tf, errno_to_pam (errno));
+ }
}
}
static void
add_char_segment (struct transform *tf, int chr)
{
struct replace_segm *segm = add_segment (tf);
- segm->type = segm_literal;
- segm->v.literal.ptr = gray_malloc (2);
- segm->v.literal.ptr[0] = chr;
- segm->v.literal.ptr[1] = 0;
- segm->v.literal.size = 1;
+ if (segm)
+ {
+ segm->type = segm_literal;
+ segm->v.literal.ptr = malloc (2);
+ if (segm->v.literal.ptr)
+ {
+ segm->v.literal.ptr[0] = chr;
+ segm->v.literal.ptr[1] = 0;
+ segm->v.literal.size = 1;
+ }
+ else
+ transform_seterr (tf, errno_to_pam (errno));
+ }
}
static void
add_backref_segment (struct transform *tf, size_t ref)
{
struct replace_segm *segm = add_segment (tf);
- segm->type = segm_backref;
- segm->v.ref = ref;
+ if (segm)
+ {
+ segm->type = segm_backref;
+ segm->v.ref = ref;
+ }
}
static void
add_case_ctl_segment (struct transform *tf, enum case_ctl_type ctl)
{
struct replace_segm *segm = add_segment (tf);
- segm->type = segm_case_ctl;
- segm->v.ctl = ctl;
+ if (segm)
+ {
+ segm->type = segm_case_ctl;
+ segm->v.ctl = ctl;
+ }
}
-static const char *
-parse_transform_expr (const char *expr)
+static int
+parse_transform_expr (const char *expr, const char **endp)
{
int delim;
int i, j, rc;
- char *str, *beg, *cur;
+ char *str;
+ const char *beg;
+ const char *cur;
const char *p;
int cflags = 0;
struct transform *tf = new_transform ();
if (expr[0] != 's')
- gray_raise ("Invalid transform expression");
+ {
+ _pam_log(LOG_ERR, "invalid transform expression");
+ *endp = expr;
+ return PAM_SERVICE_ERR;
+ }
delim = expr[1];
/* Scan regular expression */
for (i = 2; expr[i] && expr[i] != delim; i++)
if (expr[i] == '\\' && expr[i+1])
i++;
if (expr[i] != delim)
- gray_raise ("Invalid transform expression");
+ {
+ _pam_log(LOG_ERR, "invalid transform expression");
+ *endp = expr + i;
+ return PAM_SERVICE_ERR;
+ }
/* Scan replacement expression */
for (j = i + 1; expr[j] && expr[j] != delim; j++)
if (expr[j] == '\\' && expr[j+1])
j++;
if (expr[j] != delim)
- gray_raise ("Invalid transform expression");
+ {
+ _pam_log(LOG_ERR, "invalid transform expression");
+ *endp = expr + j;
+ return PAM_SERVICE_ERR;
+ }
/* Check flags */
tf->transform_type = transform_first;
for (p = expr + j + 1; *p && *p != ';'; p++)
switch (*p)
{
@@ -215,59 +275,87 @@ parse_transform_expr (const char *expr)
case '5': case '6': case '7': case '8': case '9':
tf->match_number = strtoul (p, (char**) &p, 0);
p--;
break;
default:
- gray_raise("Unknown flag in transform expression: %c", *p);
+ _pam_log(LOG_ERR, "unknown flag in transform expression: %c", *p);
+ *endp = p;
+ return PAM_SERVICE_ERR;
}
if (*p == ';')
p++;
/* Extract and compile regex */
- str = gray_malloc (i - 1);
+ str = malloc (i - 1);
+ if (!str)
+ {
+ *endp = p;
+ return errno_to_pam (errno);
+ }
memcpy (str, expr + 2, i - 2);
str[i - 2] = 0;
rc = regcomp (&tf->regex, str, cflags);
if (rc)
{
char errbuf[512];
regerror (rc, &tf->regex, errbuf, sizeof (errbuf));
- gray_raise("Invalid transform expression: %s", errbuf);
+ _pam_log(LOG_ERR, "invalid transform expression: %s", errbuf);
+ free (str);
+ *endp = p;
+ return PAM_SERVICE_ERR;
}
tf->has_regex = 1;
if (str[0] == '^' || str[strlen (str) - 1] == '$')
tf->transform_type = transform_first;
free (str);
/* Extract and compile replacement expr */
i++;
- str = gray_malloc (j - i + 1);
+ str = malloc (j - i + 1);
+ if (!str)
+ {
+ *endp = p;
+ return errno_to_pam (errno);
+ }
+
memcpy (str, expr + i, j - i);
str[j - i] = 0;
for (cur = beg = str; *cur;)
{
+ if (transform_err (tf))
+ {
+ *endp = expr + i + (beg - str);
+ free (str);
+ return transform_err (tf);
+ }
+
if (*cur == '\\')
{
size_t n;
add_literal_segment (tf, beg, cur);
switch (*++cur)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- n = strtoul (cur, &cur, 10);
+ n = strtoul (cur, (char**)&cur, 10);
if (n > tf->regex.re_nsub)
- gray_raise ("Invalid transform replacement: "
- "back reference out of range");
- add_backref_segment (tf, n);
+ {
+ _pam_log(LOG_ERR,
+ "invalid transform replacement: "
+ "back reference out of range");
+ transform_seterr (tf, PAM_SERVICE_ERR);
+ }
+ else
+ add_backref_segment (tf, n);
break;
case '\\':
add_char_segment (tf, '\\');
cur++;
break;
@@ -364,48 +452,66 @@ parse_transform_expr (const char *expr)
beg = ++cur;
}
else
cur++;
}
add_literal_segment (tf, beg, cur);
-
- return p;
+ if (transform_err (tf))
+ {
+ *endp = expr + i + (beg - str);
+ free (str);
+ return transform_err (tf);
+ }
+ *endp = p;
+ return 0;
}
-void
+int
gray_set_transform_expr (const char *expr)
{
while (*expr)
- expr = parse_transform_expr (expr);
+ {
+ int rc = parse_transform_expr (expr, &expr);
+ if (rc != PAM_SUCCESS)
+ {
+ gray_free_transform_expr ();
+ return rc;
+ }
+ }
+ return PAM_SUCCESS;
}
void
-gray_free_transform_expr ()
+gray_free_transform_expr (void)
{
while (transform_head)
{
struct transform *next = transform_head->next;
free_transform (transform_head);
transform_head = next;
}
transform_tail = NULL;
+ free (case_ctl_buffer);
+ case_ctl_buffer = NULL;
+ case_ctl_bufsize = 0;
}
/* Run case conversion specified by CASE_CTL on array PTR of SIZE
characters. Returns pointer to statically allocated storage. */
static char *
run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
{
- static char *case_ctl_buffer;
- static size_t case_ctl_bufsize;
char *p;
if (case_ctl_bufsize < size)
{
+ p = realloc (case_ctl_buffer, size);
+ if (!p)
+ return NULL;
+ case_ctl_buffer = p;
case_ctl_bufsize = size;
- case_ctl_buffer = gray_realloc (case_ctl_buffer, case_ctl_bufsize);
}
memcpy (case_ctl_buffer, ptr, size);
switch (case_ctl)
{
case ctl_upcase_next:
case_ctl_buffer[0] = toupper (case_ctl_buffer[0]);
@@ -429,13 +535,13 @@ run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
break;
}
return case_ctl_buffer;
}
-void
+static int
_single_transform_name_to_slist (struct transform *tf, gray_slist_t slist,
char *input)
{
regmatch_t *rmp;
int rc;
size_t nmatches = 0;
@@ -447,14 +553,15 @@ _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist,
|| case_ctl == ctl_locase_next) \
{ \
case_ctl = save_ctl; \
save_ctl = ctl_stop; \
}
- rmp = gray_malloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
-
+ rmp = malloc ((tf->regex.re_nsub + 1) * sizeof (*rmp));
+ if (!rmp)
+ return errno;
while (*input)
{
size_t disp;
char *ptr;
rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
@@ -485,12 +592,14 @@ _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist,
ptr = segm->v.literal.ptr;
else
{
ptr = run_case_conv (case_ctl,
segm->v.literal.ptr,
segm->v.literal.size);
+ if (!ptr)
+ return errno;
CASE_CTL_RESET();
}
gray_slist_append (slist, ptr, segm->v.literal.size);
break;
case segm_backref: /* Back-reference segment */
@@ -500,12 +609,14 @@ _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist,
size_t size = rmp[segm->v.ref].rm_eo
- rmp[segm->v.ref].rm_so;
ptr = input + rmp[segm->v.ref].rm_so;
if (case_ctl != ctl_stop)
{
ptr = run_case_conv (case_ctl, ptr, size);
+ if (!ptr)
+ return errno;
CASE_CTL_RESET();
}
gray_slist_append (slist, ptr, size);
}
break;
@@ -548,23 +659,38 @@ _single_transform_name_to_slist (struct transform *tf, gray_slist_t slist,
break;
}
}
gray_slist_append_char (slist, 0);
free (rmp);
+ return gray_slist_err (slist);
}
int
gray_transform_name_to_slist (gray_slist_t slist, char *input, char **output)
{
- struct transform *tf;
-
- for (tf = transform_head; tf; tf = tf->next)
+ if (transform_head)
+ {
+ struct transform *tf;
+ for (tf = transform_head; tf; tf = tf->next)
+ {
+ int rc = _single_transform_name_to_slist (tf, slist, input);
+ if (rc)
+ return errno_to_pam(rc);
+ input = gray_slist_finish (slist);
+ if (!input)
+ return errno_to_pam(errno);
+ }
+ }
+ else
{
- _single_transform_name_to_slist (tf, slist, input);
+ gray_slist_append(slist, input, strlen(input) + 1);
input = gray_slist_finish (slist);
+ if (!input)
+ return errno_to_pam(errno);
}
*output = input;
- return transform_head != NULL;
+
+ return PAM_SUCCESS;
}
diff --git a/pam_groupmember/pam_groupmember.c b/pam_groupmember/pam_groupmember.c
index 7045d13..44be0f8 100644
--- a/pam_groupmember/pam_groupmember.c
+++ b/pam_groupmember/pam_groupmember.c
@@ -163,13 +163,12 @@ check_membership0(pam_handle_t *pamh, int argc, const char **argv)
char *name;
char **groupnames;
int rc;
struct passwd *pw;
static int retval[] = { PAM_SUCCESS, PAM_AUTH_ERR };
- gray_pam_init(PAM_AUTHINFO_UNAVAIL);
gray_log_init(0, MODULE_NAME, LOG_AUTHPRIV);
gray_parseopt(pam_opt, argc, argv);
if (!groups) {
_pam_log(LOG_ERR, "no group names given");
return PAM_SERVICE_ERR;
}
diff --git a/pam_innetgr/pam_innetgr.c b/pam_innetgr/pam_innetgr.c
index a926737..96830b8 100644
--- a/pam_innetgr/pam_innetgr.c
+++ b/pam_innetgr/pam_innetgr.c
@@ -192,13 +192,12 @@ check_netgroup0(pam_handle_t *pamh, int argc, const char **argv,
domain_name = NULL;
netgroup_name = NULL;
use_getdomainname = 1;
use_resolve = 1;
sense = SENSE_ALLOW;
- gray_pam_init(PAM_AUTHINFO_UNAVAIL);
gray_log_init(0, MODULE_NAME, LOG_AUTHPRIV);
gray_parseopt(pam_opt, argc, argv);
if (!netgroup_name) {
_pam_log(LOG_ERR, "no netgroup name given");
return PAM_AUTHINFO_UNAVAIL;
}
diff --git a/pam_ldaphome/pam_ldaphome.c b/pam_ldaphome/pam_ldaphome.c
index dd3f9e3..0b492dd 100644
--- a/pam_ldaphome/pam_ldaphome.c
+++ b/pam_ldaphome/pam_ldaphome.c
@@ -174,13 +174,13 @@ get_intval(struct gray_env *env, const char *name, int base, unsigned long *pv)
name);
return -1;
}
return 0;
}
-char *
+static char *
parse_ldap_uri(const char *uri)
{
int wc;
char **wv;
LDAPURLDesc *ludlist, **ludp;
char **urls = NULL;
@@ -719,31 +719,41 @@ get_pubkeys(LDAP *ld, const char *base, const char *filter, const char *attr)
static int
check_groups(int gc, char **gv, const char *username, gid_t gid)
{
int i;
struct group *gp;
char *pgname;
-
+ int rc = 1;
+
gp = getgrgid(gid);
- pgname = gp ? gray_strdup(gp->gr_name) : NULL;
- for (i = 0; i < gc; i++) {
+ if (gp) {
+ pgname = strdup(gp->gr_name);
+ if (!pgname) {
+ errno_to_pam(errno);
+ return -1;
+ }
+ } else
+ gp = NULL;
+ for (i = 0; rc && i < gc; i++) {
if (strcmp(gv[i], pgname) == 0) {
- free(pgname);
- return 0;
+ rc = 0;
+ break;
}
gp = getgrnam(gv[i]);
if (gp) {
char **p;
- for (p = gp->gr_mem; *p; p++)
+ for (p = gp->gr_mem; *p; p++) {
if (strcmp(username, *p) == 0) {
- free(pgname);
- return 0;
+ rc = 0;
+ break;
}
+ }
}
}
- return 1;
+ free(pgname);
+ return rc;
}
static int
check_user_groups(pam_handle_t *pamh, struct gray_env *env,
struct passwd **ppw, int *retval)
{
@@ -853,81 +863,64 @@ copy_file(pam_handle_t *pamh, const char *src, const char *dst,
close(sfd);
close(dfd);
return rc;
}
-#define INITIAL_READLINK_SIZE 128
-
-int
-read_link_name(const char *name, char **pbuf, size_t *psize, size_t *plen)
+static int
+read_link_name(const char *name, char **pbuf)
{
int rc = 0;
- char *buf = *pbuf;
- size_t size = *psize;
- ssize_t linklen;
+ char *buf = NULL;
+ size_t size = 0;
+ ssize_t linklen = 0;
while (1) {
- if (!buf) {
- size = INITIAL_READLINK_SIZE;
- buf = malloc(size);
- } else {
- char *p;
- size_t newsize = size << 1;
- if (newsize < size) {
- rc = ENAMETOOLONG;
+ if (linklen == size) {
+ char *p = gray_2nrealloc(&buf, &size, 1);
+ if (!p) {
+ errno_to_pam(errno);
+ rc = 1;
break;
}
- size = newsize;
- p = realloc(buf, size);
- if (!p)
- free(buf);
buf = p;
- }
- if (!buf) {
- rc = 1;
- break;
+ linklen = size;
}
linklen = readlink(name, buf, size);
if (linklen < 0 && errno != ERANGE) {
rc = 1;
break;
}
- if ((size_t) linklen < size) {
+ if (linklen < size) {
buf[linklen++] = '\0';
rc = 0;
break;
}
}
if (rc) {
if (buf) {
free(buf);
buf = NULL;
}
- size = 0;
}
*pbuf = buf;
- *psize = size;
- if (plen)
- *plen = linklen;
return rc;
}
static int
copy_link(pam_handle_t *pamh, const char *src, const char *dst,
char *buffer, size_t bufsize, struct stat *st)
{
- char *lnkname = NULL;
- size_t lnklen = 0;
+ char *lnkname;
int rc;
- if (read_link_name(src, &lnkname, &lnklen, NULL)) {
+ if (read_link_name(src, &lnkname)) {
_pam_log(LOG_ERR, "error reading link %s: %s",
src, strerror(errno));
return 1;
}
rc = symlink(lnkname, dst);
if (rc)
@@ -996,13 +989,17 @@ create_interdir(const char *path, struct passwd *pw)
int rc;
p = strrchr(path, '/');
if (!p)
return 1;
len = p - path;
- dir = gray_malloc(len + 1);
+ dir = malloc(len + 1);
+ if (!dir) {
+ errno_to_pam(errno);
+ return -1;
+ }
memcpy(dir, path, len);
dir[len] = 0;
rc = create_hierarchy(dir, strlen(pw->pw_dir));
if (rc == 0)
rc = chown(dir, pw->pw_uid, pw->pw_gid);
free(dir);
@@ -1265,25 +1262,46 @@ struct pubkeyfile {
size_t size; /* Size of base */
char **lnv; /* File contents parsed into nul-terminated lines */
size_t lnc; /* Number of lines in lnv */
size_t lnm; /* Max. capacity of lnv */
};
+/* Close the public key file */
+static void
+pubkeyfile_close(struct pubkeyfile *pkb)
+{
+ close(pkb->fd);
+ free(pkb->file_name);
+ free(pkb->base);
+ free(pkb->lnv);
+
+ pkb->fd = -1;
+ pkb->file_name = NULL;
+ pkb->base = NULL;
+ pkb->lnv = NULL;
+}
+
/* Open public key file NAME. Return 0 on success. On error, issue a
diagnostic message and return -1. */
static int
pubkeyfile_open(struct pubkeyfile *pkb, char *name)
{
memset(pkb, 0, sizeof *pkb);
pkb->fd = open(name, O_CREAT|O_RDWR, 0666);
if (pkb->fd == -1) {
_pam_log(LOG_ERR, "can't open %s: %s",
name, strerror(errno));
return -1;
}
- pkb->file_name = gray_strdup(name);
+ pkb->file_name = strdup(name);
+ if (!pkb->file_name) {
+ int rc = errno_to_pam(errno);
+ close(pkb->fd);
+ pkb->fd = -1;
+ return rc;
+ }
return 0;
}
/* Read in the contents of the open public key file PKB. */
static int
pubkeyfile_read(struct pubkeyfile *pkb)
@@ -1295,26 +1313,33 @@ pubkeyfile_read(struct pubkeyfile *pkb)
if (fstat(pkb->fd, &st)) {
_pam_log(LOG_ERR, "fstat %s: %s",
pkb->file_name, strerror(errno));
return -1;
}
pkb->size = st.st_size;
- pkb->base = gray_malloc(st.st_size + 1);
+ pkb->base = malloc(st.st_size + 1);
+ if (!pkb->base) {
+ errno_to_pam(errno);
+ return -1;
+ }
if (full_read(pkb->fd, pkb->file_name, pkb->base, pkb->size)) {
_pam_log(LOG_ERR, "fread %s: %s",
pkb->file_name, strerror(errno));
return -1;
}
pkb->base[pkb->size] = 0;
pkb->lnc = 0;
for (p = pkb->base; *p; p++)
if (*p == '\n')
++pkb->lnc;
pkb->lnm = pkb->lnc + 1;
- pkb->lnv = gray_calloc(pkb->lnm, sizeof(pkb->lnv[0]));
-
+ pkb->lnv = calloc(pkb->lnm, sizeof(pkb->lnv[0]));
+ if (pkb->lnv) {
+ errno_to_pam(errno);
+ return -1;
+ }
i = 0;
for (p = pkb->base; *p; p++) {
if (p == pkb->base || p[-1] == 0)
pkb->lnv[i++] = p;
if (*p == '\n')
*p = 0;
@@ -1326,13 +1351,16 @@ pubkeyfile_read(struct pubkeyfile *pkb)
/* Open the public key file NAME and read its contents. */
static int
pubkeyfile_init(struct pubkeyfile *pkb, char *name)
{
if (pubkeyfile_open(pkb, name))
return -1;
- return pubkeyfile_read(pkb);
+ if (pubkeyfile_read(pkb) == 0)
+ return 0;
+ pubkeyfile_close(pkb);
+ return -1;
}
/* Write data from lnv into the public key file, overwriting its current
content. */
static int
pubkeyfile_write(struct pubkeyfile *pkb)
@@ -1385,57 +1413,54 @@ pubkeyfile_remove_lines(struct pubkeyfile *pkb, int pos, int count)
(pkb->lnc - pos - count + 1) * sizeof(pkb->lnv[0]));
pkb->lnc -= count;
}
/* Allocate COUNT lines starting from position POS in PKB, preserving
the existing data. */
-static void
+static int
pubkeyfile_alloc_lines(struct pubkeyfile *pkb, size_t pos, size_t count)
{
if (pos > pkb->lnc) {
_pam_log(LOG_ERR, "%s:%d: INTERNAL ERROR: pos out of range",
__FILE__, __LINE__);
- abort();
+ return PAM_SERVICE_ERR;
}
if (pkb->lnc + count + 1 > pkb->lnm) {
- pkb->lnm += count;
- pkb->lnv = gray_realloc(pkb->lnv,
- pkb->lnm * sizeof(pkb->lnv[0]));
+ char **p;
+ size_t lnm = pkb->lnm + count;
+ p = realloc(pkb->lnv, lnm * sizeof(pkb->lnv[0]));
+ if (!p)
+ return errno_to_pam(errno);
+ pkb->lnv = p;
+ pkb->lnm = lnm;
}
memmove(pkb->lnv + pos + count, pkb->lnv + pos,
(pkb->lnc - pos + 1) * sizeof(pkb->lnv[0]));
pkb->lnc += count;
+ return PAM_SUCCESS;
}
/* Insert lines from LV in position POS in the file PKB, shifting down
existing lines as necessary. */
-void
+static int
pubkeyfile_insert_lines(struct pubkeyfile *pkb, size_t pos, char **lv)
{
size_t i;
size_t lc;
+ int rc;
for (lc = 0; lv[lc]; lc++)
;
- pubkeyfile_alloc_lines(pkb, pos, lc);
-
- for (i = 0; i < lc; i++)
- pkb->lnv[pos + i] = lv[i];
-}
-
-/* Close the public key file */
-void
-pubkeyfile_close(struct pubkeyfile *pkb)
-{
- close(pkb->fd);
- free(pkb->file_name);
- free(pkb->base);
- free(pkb->lnv);
+ rc = pubkeyfile_alloc_lines(pkb, pos, lc);
+ if (rc == 0) {
+ for (i = 0; i < lc; i++)
+ pkb->lnv[pos + i] = lv[i];
+ }
+ return rc;
}
-
static int
store_pubkeys(char **keys, struct passwd *pw, struct gray_env *env)
{
int rc;
char *file_name;
@@ -1448,13 +1473,15 @@ store_pubkeys(char **keys, struct passwd *pw, struct gray_env *env)
homelen = strlen(pw->pw_dir);
pathlen = strlen(authorized_keys_file);
len = homelen + pathlen;
if (pw->pw_dir[homelen - 1] != '/')
len++;
- file_name = gray_malloc(len + 1);
+ file_name = malloc(len + 1);
+ if (!file_name)
+ return errno_to_pam(errno);
memcpy(file_name, pw->pw_dir, homelen);
if (pw->pw_dir[homelen - 1] != '/')
file_name[homelen++] = '/';
strcpy(file_name + homelen, authorized_keys_file);
switch (get_intval(env, "keyfile-mode", 8, &mode)) {
@@ -1517,15 +1544,17 @@ store_pubkeys(char **keys, struct passwd *pw, struct gray_env *env)
update = 1;
}
}
if (update) {
pubkeyfile_remove_lines(&pkf, 0, i);
- pubkeyfile_insert_lines(&pkf, 0, keys);
- pubkeyfile_write(&pkf);
- retval = PAM_TRY_AGAIN;
+ retval = pubkeyfile_insert_lines(&pkf, 0, keys);
+ if (retval == PAM_SUCCESS) {
+ pubkeyfile_write(&pkf);
+ retval = PAM_TRY_AGAIN;
+ }
} else
retval = PAM_SUCCESS;
pubkeyfile_close(&pkf);
free(file_name);
return retval;
@@ -1557,26 +1586,33 @@ import_public_key(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env)
return PAM_SERVICE_ERR;
if (ldap_bind(ld, env))
retval = PAM_SERVICE_ERR;
else {
char *filter;
gray_slist_t slist;
- char **keys;
slist = gray_slist_create();
- gray_expand_string(pamh, filter_pat, slist);
- gray_slist_append_char(slist, 0);
- filter = gray_slist_finish(slist);
-
- keys = get_pubkeys(ld, base, filter, attr);
- gray_slist_free(&slist);
- if (keys) {
- retval = store_pubkeys(keys, pw, env);
- argcvz_free(keys);
- } else
- retval = PAM_SUCCESS;
+ if (!slist)
+ retval = errno_to_pam(errno);
+ else {
+ gray_expand_string(pamh, filter_pat, slist);
+ gray_slist_append_char(slist, 0);
+ filter = gray_slist_finish(slist);
+ if (filter) {
+ char **keys = get_pubkeys(ld, base, filter,
+ attr);
+ if (keys) {
+ retval = store_pubkeys(keys, pw, env);
+ argcvz_free(keys);
+ } else
+ retval = PAM_SUCCESS;
+ } else {
+ retval = errno_to_pam(gray_slist_err(slist));
+ }
+ gray_slist_free(&slist);
+ }
}
ldap_unbind(ld);
return retval;
}
static int
@@ -1691,38 +1727,54 @@ locate_unset(char **env, const char *name)
}
}
}
return 0;
}
+/* Concatenate NAMELEN bytes from NAME, "=", A, and B. Allocate the
+ result using malloc.
+
+ On ENOMEM, log a diagnostic message and exit with code 127. This function
+ should be used from child process only.
+*/
static char *
env_concat(char *name, size_t namelen, char *a, char *b)
{
char *res;
size_t len;
if (a && b) {
- res = gray_malloc(namelen + 1 + strlen(a) + strlen(b) + 1);
- strcpy(res + namelen + 1, a);
- strcat(res, b);
+ res = malloc(namelen + 1 + strlen(a) + strlen(b) + 1);
+ if (res) {
+ strcpy(res + namelen + 1, a);
+ strcat(res, b);
+ }
} else if (a) {
len = strlen(a);
if (ispunct(a[len-1]))
len--;
- res = gray_malloc(namelen + 1 + len + 1);
- memcpy(res + namelen + 1, a, len);
- res[namelen + 1 + len] = 0;
+ res = malloc(namelen + 1 + len + 1);
+ if (res) {
+ memcpy(res + namelen + 1, a, len);
+ res[namelen + 1 + len] = 0;
+ }
} else /* if (a == NULL) */ {
if (ispunct(b[0]))
b++;
len = strlen(b);
- res = gray_malloc(namelen + 1 + len + 1);
- strcpy(res + namelen + 1, b);
+ res = malloc(namelen + 1 + len + 1);
+ if (res)
+ strcpy(res + namelen + 1, b);
}
- memcpy(res, name, namelen);
- res[namelen] = '=';
+ if (res) {
+ memcpy(res, name, namelen);
+ res[namelen] = '=';
+ } else {
+ errno_to_pam(errno);
+ _exit(127);
+ }
return res;
}
static char **
parsenv(char *str)
{
@@ -1736,12 +1788,20 @@ parsenv(char *str)
st_end
} state = st_init, prev_state;
# define setstate(s) do { prev_state = state; state = s; } while (0)
char *p, *kw;
char **wv = NULL;
size_t wi = 0, wc = 0;
+
+# define ASSERT_NOTNULL(p) do { \
+ if (!(p)) { \
+ errno_to_pam(errno); \
+ _exit(127); \
+ } \
+ } while (0)
+
if (!str)
return NULL;
for (p = str; *p; ++p) {
switch (state) {
@@ -1788,34 +1848,33 @@ parsenv(char *str)
if (state == st_end) {
size_t len = p - kw;
char *q;
if (wi == wc) {
- if (wc == 0)
- wc = 4;
- else
- wc *= 2;
- wv = gray_realloc(wv, wc * sizeof(wv[0]));
+ wv = gray_2nrealloc(wv, &wc, sizeof(wv[0]));
+ ASSERT_NOTNULL(wv);
}
switch (prev_state) {
case st_squote:
len -= 2;
- wv[wi] = gray_malloc(len + 1);
+ wv[wi] = malloc(len + 1);
+ ASSERT_NOTNULL(wv[wi]);
for (q = wv[wi]; *kw; ) {
if (*kw == '\'')
++kw;
else
*q++ = *kw++;
}
*q = 0;
break;
case st_dquote:
len -= 2;
- wv[wi] = gray_malloc(len + 1);
+ wv[wi] = malloc(len + 1);
+ ASSERT_NOTNULL(wv[wi]);
q = wv[wi];
while ((*q++ = *kw++) != '=')
;
while (*kw != '"')
*q++ = *kw++;
++kw;
@@ -1824,36 +1883,44 @@ parsenv(char *str)
++kw;
*q++ = *kw++;
}
*q = 0;
break;
default:
- wv[wi] = gray_malloc(len + 1);
+ wv[wi] = malloc(len + 1);
+ ASSERT_NOTNULL(wv[wi]);
memcpy(wv[wi], kw, len);
wv[wi][len] = 0;
}
++wi;
setstate(st_init);
}
}
if (state != st_init) {
if (wc == wi) {
- ++wc;
- wv = gray_realloc(wv, (wc + 1) * sizeof(wv[0]));
+ wv = gray_2nrealloc(wv, &wc, sizeof(wv[0]));
+ ASSERT_NOTNULL(wv);
}
- wv[wi++] = gray_strdup(kw);
+ wv[wi] = strdup(kw);
+ ASSERT_NOTNULL(wv[wi]);
+ ++wi;
}
- if (wc == wi)
- wv = gray_realloc(wv, (wc + 1) * sizeof(wv[0]));
+ if (wc == wi) {
+ wv = gray_2nrealloc(wv, &wc, sizeof(wv[0]));
+ ASSERT_NOTNULL(wv);
+ }
wv[wi] = NULL;
return wv;
}
+/* Setup environment for exec* family call. On ENOMEM, exit with code 127.
+ This function should be called from a child process.
+*/
static char **
env_setup(char *envstr)
{
char **env;
char **old_env = environ;
char **new_env;
@@ -1876,14 +1943,17 @@ env_setup(char *envstr)
count++;
for (i = 0; env[i]; i++)
count++;
/* Allocate the new environment. */
- new_env = gray_calloc(count + 1, sizeof new_env[0]);
-
+ new_env = calloc(count + 1, sizeof new_env[0]);
+ if (!new_env) {
+ errno_to_pam(errno);
+ _exit(127);
+ }
/* Populate the environment. */
n = 0;
if (old_env)
for (i = 0; old_env[i]; i++) {
if (!locate_unset(env, old_env[i]))
@@ -1935,15 +2005,22 @@ runas(struct passwd *pw)
while ((gr = getgrent ())) {
char **p;
if (gr->gr_gid == pw->pw_gid)
continue;
for (p = gr->gr_mem; *p; p++) {
if (strcmp (*p, pw->pw_name) == 0) {
- if (sgc == sgm)
- sgv = gray_2nrealloc(sgv, &sgm,
- sizeof(sgv[0]));
+ if (sgc == sgm) {
+ gid_t *p;
+ p = gray_2nrealloc(sgv, &sgm,
+ sizeof(sgv[0]));
+ if (!p) {
+ errno_to_pam(errno);
+ return 1; //FIXME: proper error code
+ }
+ sgv = p;
+ }
sgv[sgc++] = gr->gr_gid;
}
}
}
endgrent();
@@ -2140,18 +2217,17 @@ ldaphome_main(pam_handle_t *pamh, int flags, int argc, const char **argv,
int retval = PAM_AUTH_ERR;
struct gray_env *env;
_pam_parse(pamh, argc, argv);
DEBUG(90,("enter %s", func));
- gray_pam_init(PAM_AUTHINFO_UNAVAIL);
if (gray_env_read(config_file_name, &env) == 0) {
char *val;
struct passwd *pw;
- if (val = gray_env_get(env, "ldap-config")) {
+ if ((val = gray_env_get(env, "ldap-config"))) {
if (strcmp(val, "none") == 0)
ldap_config_name = NULL;
else
ldap_config_name = val;
}
if (ldap_config_name) {
@@ -2159,13 +2235,13 @@ ldaphome_main(pam_handle_t *pamh, int flags, int argc, const char **argv,
struct gray_env *tmp;
gray_env_read_tr(ldap_config_name, &tmp, map);
gray_env_merge(&env, &tmp);
}
- if (val = gray_env_get(env, "authorized_keys"))
+ if ((val = gray_env_get(env, "authorized_keys")))
authorized_keys_file = val;
if (check_user_groups(pamh, env, &pw, &retval) == 0) {
switch (create_home_dir(pamh, pw, env)) {
case create_ok:
retval = run_initrc(pamh, pw, env);
diff --git a/pam_log/pam_log.c b/pam_log/pam_log.c
index 96cc795..c59bc16 100644
--- a/pam_log/pam_log.c
+++ b/pam_log/pam_log.c
@@ -99,21 +99,23 @@ struct pam_opt pam_opt[] = {
{ PAM_OPTSTR(pri), pam_opt_null, NULL, { 0 }, parse_priority },
{ PAM_OPTSTR(open), pam_opt_bool, &do_open },
{ NULL }
};
-static void
+static int
_pam_parse(pam_handle_t *pamh, int argc, const char **argv)
{
int i;
const char **targv;
gray_log_init(0, MODULE_NAME, LOG_AUTHPRIV);
- targv = gray_malloc(argc * sizeof (targv[0]));
+ targv = calloc(argc, sizeof (targv[0]));
+ if (!targv)
+ return errno_to_pam(errno);
for (i = 0; i < argc; i++) {
if (argv[i][0] == '-') {
if (argv[i][1] == '-' && argv[i][2] == 0)
break;
targv[i] = argv[i] + 1;
} else
@@ -125,77 +127,81 @@ _pam_parse(pam_handle_t *pamh, int argc, const char **argv)
xargc = argc - i;
xargv = argv + i;
closelog();
gray_log_init(!do_open, syslog_tag, facility);
+ return PAM_SUCCESS;
}
static int
echo(pam_handle_t *pamh, const char *prefix, int argc, const char **argv)
{
- char *str;
- gray_slist_t slist;
-
- _pam_parse(pamh, argc, argv);
- slist = gray_slist_create();
- if (prefix) {
- gray_slist_append(slist, prefix, strlen(prefix));
- gray_slist_append(slist, ": ", 2);
+ if (_pam_parse(pamh, argc, argv) == PAM_SUCCESS) {
+ gray_slist_t slist;
+
+ slist = gray_slist_create();
+ if (!slist) {
+ errno_to_pam(errno);
+ } else {
+ char *str;
+ if (prefix) {
+ gray_slist_append(slist, prefix,
+ strlen(prefix));
+ gray_slist_append(slist, ": ", 2);
+ }
+ gray_expand_argv(pamh, xargc, xargv, slist);
+ gray_slist_append_char(slist, 0);
+ str = gray_slist_finish(slist);
+ if (str)
+ _pam_log(priority, "%s", str);
+ else
+ errno_to_pam(gray_slist_err(slist));
+ }
+ gray_slist_free(&slist);
}
- gray_expand_argv(pamh, xargc, xargv, slist);
- gray_slist_append_char(slist, 0);
- str = gray_slist_finish(slist);
- _pam_log(priority, "%s", str);
- gray_slist_free(&slist);
return PAM_IGNORE;
}
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- gray_pam_init(PAM_IGNORE);
return echo(pamh, __FUNCTION__, argc, argv);
}
PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- gray_pam_init(PAM_IGNORE);
return echo(pamh, __FUNCTION__, argc, argv);
}
PAM_EXTERN int
pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv)
{
- gray_pam_init(PAM_IGNORE);
return echo(pamh, __FUNCTION__, argc, argv);
}
PAM_EXTERN int
pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, int argc, const char **argv)
{
- gray_pam_init(PAM_IGNORE);
return echo(pamh, __FUNCTION__, argc, argv);
}
PAM_EXTERN int
pam_sm_open_session (pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
- gray_pam_init(PAM_IGNORE);
return echo(pamh, __FUNCTION__, argc, argv);
}
PAM_EXTERN int
pam_sm_close_session (pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
- gray_pam_init(PAM_IGNORE);
return echo(pamh, __FUNCTION__, argc, argv);
}
#ifdef PAM_STATIC
/* static module data */
diff --git a/pam_regex/pam_regex.c b/pam_regex/pam_regex.c
index 95324c0..0c3737b 100644
--- a/pam_regex/pam_regex.c
+++ b/pam_regex/pam_regex.c
@@ -109,13 +109,12 @@ pam_sm_authenticate(pam_handle_t *pamh,
regex_t rx;
_pam_parse(pamh, argc, argv);
DEBUG(90,("enter pam_sm_authenticate"));
- gray_pam_init(PAM_AUTHINFO_UNAVAIL);
/*
* get username
*/
retval = pam_get_user(pamh, (const char**)&name, "login: ");
if (retval == PAM_SUCCESS) {
@@ -126,29 +125,38 @@ pam_sm_authenticate(pam_handle_t *pamh,
}
if (transform) {
char *newname;
gray_slist_t slist;
- gray_set_transform_expr(transform);
+ retval = gray_set_transform_expr(transform);
+ if (retval != PAM_SUCCESS)
+ return retval;
slist = gray_slist_create();
- gray_transform_name_to_slist(slist, name, &newname);
- DEBUG(90,("new name: %s", newname));
- MAKE_STR(pamh, newname, name);
- retval = pam_set_item(pamh, PAM_USER, name);
- gray_slist_free(&slist);
- gray_free_transform_expr();
+ if (!slist)
+ retval = errno_to_pam(errno);
+ else {
+ retval = gray_transform_name_to_slist(slist, name,
+ &newname);
+ if (retval == PAM_SUCCESS) {
+ DEBUG(90,("new name: %s", newname));
+ MAKE_STR(pamh, newname, name);
+ retval = pam_set_item(pamh, PAM_USER, name);
+ gray_slist_free(&slist);
+ }
+ gray_free_transform_expr();
+ }
if (retval != PAM_SUCCESS) {
_pam_log(LOG_ERR, "retval %d", retval);
return PAM_AUTHINFO_UNAVAIL;
}
}
if (regex) {
for (;;) {
- if (rc = regcomp(&rx, regex, regex_flags)) {
+ if ((rc = regcomp(&rx, regex, regex_flags)) != 0) {
char errbuf[512];
regerror (rc, &rx, errbuf, sizeof (errbuf));
_pam_log(LOG_ERR, "can't compile regex: %s",
errbuf);
retval = PAM_AUTHINFO_UNAVAIL;
break;
diff --git a/pam_sql/pam_mysql.c b/pam_sql/pam_mysql.c
index ca1f9e6..3f4a0d6 100644
--- a/pam_sql/pam_mysql.c
+++ b/pam_sql/pam_mysql.c
@@ -362,17 +362,21 @@ gpam_sql_verify_user_pass(pam_handle_t *pamh, const char *password,
gray_slist_t slist;
rc = check_query_result(&mysql, password);
/* FIXME: This comment is needed to pacify
`make check-sql-config' in doc:
gpam_sql_find_config("setenv-query") */
- if (rc == PAM_SUCCESS
- && (q = gpam_sql_get_query(pamh, "setenv-query",
- &slist, 0))) {
- mysql_setenv(pamh, &mysql, q);
- gray_slist_free(&slist);
+ if (rc == PAM_SUCCESS) {
+ rc = gpam_sql_get_query(pamh, "setenv-query", 0,
+ &slist, &q);
+ if (rc == PAM_SUCCESS) {
+ if (q) {
+ mysql_setenv(pamh, &mysql, q);
+ gray_slist_free(&slist);
+ }
+ }
}
mysql_close(&mysql);
}
return rc;
}
diff --git a/pam_sql/pam_pgsql.c b/pam_sql/pam_pgsql.c
index f6d19e1..5f66b53 100644
--- a/pam_sql/pam_pgsql.c
+++ b/pam_sql/pam_pgsql.c
@@ -112,13 +112,14 @@ gpam_sql_verify_user_pass(pam_handle_t *pamh, const char *password,
_pam_log(LOG_ERR, "PQexec: query did not return tuples");
rc = PAM_SERVICE_ERR;
} else {
char *p;
int n;
gray_slist_t slist;
-
+ char const *query;
+
n = PQntuples(res);
DEBUG(20,("Returned %d tuples", n));
if (n != 1) {
_pam_log(LOG_WARNING,
"PQexec: query returned %d tuples", n);
if (n == 0) {
@@ -150,18 +151,21 @@ gpam_sql_verify_user_pass(pam_handle_t *pamh, const char *password,
&& strcmp (p, password) == 0)
rc = PAM_SUCCESS;
/* FIXME: This comment is needed to pacify
`make check-sql-config' in doc:
gpam_sql_find_config("setenv-query") */
- if (rc == PAM_SUCCESS
- && (query = gpam_sql_get_query(pamh,
- "setenv-query",
- &slist, 0))) {
- pgsql_setenv(pamh, pgconn, query);
- gray_slist_free(&slist);
+ if (rc == PAM_SUCCESS) {
+ rc = gpam_sql_get_query(pamh, "setenv-query", 0,
+ &slist, &query);
+ if (rc == PAM_SUCCESS) {
+ if (query) {
+ pgsql_setenv(pamh, pgconn, query);
+ gray_slist_free(&slist);
+ }
+ }
}
}
PQclear(res);
PQfinish(pgconn);
diff --git a/pam_sql/pam_sql.c b/pam_sql/pam_sql.c
index 359ba64..6707eb3 100644
--- a/pam_sql/pam_sql.c
+++ b/pam_sql/pam_sql.c
@@ -156,66 +156,56 @@ gpam_sql_check_boolean_config(const char *name, int defval)
if (value)
defval = gray_boolean_true_p(value);
return defval;
}
-const char *
-gpam_sql_get_query(pam_handle_t *pamh, const char *name, gray_slist_t *pslist,
- int required)
+int
+gpam_sql_get_query(pam_handle_t *pamh, const char *name, int required,
+ gray_slist_t *pslist, const char **retptr)
{
gray_slist_t slist;
const char *query = gpam_sql_find_config(name);
-
- if (!query) {
- if (required)
- gray_raise("%s: %s not defined", gpam_sql_config_file, name);
- return NULL;
- }
-
- slist = gray_slist_create();
- gray_expand_string(pamh, query, slist);
- gray_slist_append_char(slist, 0);
- *pslist = slist;
- return gray_slist_finish(slist);
-}
-
-static const char *
-get_query2(pam_handle_t *pamh, const char *name1, const char *name2,
- gray_slist_t *pslist, int required)
-{
- gray_slist_t slist;
- const char *query = gpam_sql_find_config(name1);
-
- if (!query)
- query = gpam_sql_find_config(name2);
+ char *retval;
if (!query) {
- if (required)
- gray_raise("%s: %s not defined",
- gpam_sql_config_file, name1);
- return NULL;
+ if (required) {
+ _pam_log(LOG_ERR, "%s: %s not defined",
+ gpam_sql_config_file, name);
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+ *pslist = NULL;
+ *retptr = NULL;
+ return PAM_SUCCESS;
}
slist = gray_slist_create();
+ if (!slist)
+ return errno_to_pam(errno);
gray_expand_string(pamh, query, slist);
gray_slist_append_char(slist, 0);
*pslist = slist;
- return gray_slist_finish(slist);
+ retval = gray_slist_finish(slist);
+ if (gray_slist_err(slist)) {
+ int rc = errno_to_pam(gray_slist_err(slist));
+ gray_slist_free(&slist);
+ return rc;
+ }
+ *retptr = retval;
+ return PAM_SUCCESS;
}
/* --- authentication management functions (only) --- */
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
const char *username;
char *password;
int retval = PAM_AUTH_ERR;
- gray_pam_init(PAM_SERVICE_ERR);
/* parse arguments */
_pam_parse(argc, argv);
/* Get the username */
retval = pam_get_user(pamh, &username, NULL);
@@ -234,19 +224,24 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
}
if (gray_env_read(gpam_sql_config_file, &config_env))
retval = PAM_SERVICE_ERR;
else {
gray_slist_t slist;
+ char const *query;
+
/* FIXME: This comment is needed to pacify
`make check-sql-config' in doc:
gpam_sql_find_config("passwd-query") */
- retval = gpam_sql_verify_user_pass(pamh, password,
- get_query2(pamh, "passwd-query",
- "query", &slist, 1));
- gray_slist_free(&slist);
+ retval = gpam_sql_get_query(pamh, "passwd-query", 1,
+ &slist, &query);
+ if (retval == PAM_SUCCESS) {
+ retval = gpam_sql_verify_user_pass(pamh, password,
+ query);
+ gray_slist_free(&slist);
+ }
}
gray_env_free(config_env);
config_env = NULL;
switch (retval) {
@@ -273,25 +268,29 @@ pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
static int
sql_session_mgmt(pam_handle_t *pamh, int flags,
int argc, const char **argv, const char *query_name)
{
int retval;
- gray_pam_init(PAM_SERVICE_ERR);
/* parse arguments */
_pam_parse(argc, argv);
if (gray_env_read(gpam_sql_config_file, &config_env))
retval = PAM_SERVICE_ERR;
else {
gray_slist_t slist;
- retval = gpam_sql_acct(pamh,
- gpam_sql_get_query(pamh, query_name,
- &slist, 0));
- gray_slist_free(&slist);
+ char const *query;
+
+ retval = gpam_sql_get_query(pamh, query_name, 0, &slist, &query);
+ if (retval == PAM_SUCCESS) {
+ if (query) {
+ retval = gpam_sql_acct(pamh, query);
+ gray_slist_free(&slist);
+ }
+ }
}
gray_env_free(config_env);
config_env = NULL;
return retval;
diff --git a/pam_sql/pam_sql.h b/pam_sql/pam_sql.h
index 9eeecd6..5dc9525 100644
--- a/pam_sql/pam_sql.h
+++ b/pam_sql/pam_sql.h
@@ -44,10 +44,11 @@ extern char *gpam_sql_config_file;
int gpam_sql_verify_user_pass(pam_handle_t *pamh, const char *passwd,
const char *query);
int gpam_sql_acct(pam_handle_t *pamh, const char *query);
char *gpam_sql_find_config(const char *name);
-const char *gpam_sql_get_query(pam_handle_t *pamh, const char *name,
- gray_slist_t *pslist, int required);
+int gpam_sql_get_query(pam_handle_t *pamh, char const *var,
+ int required,
+ gray_slist_t *pslist, const char **query);
int gpam_sql_check_boolean_config(const char *name, int defval);
diff --git a/pam_umotd/pam_umotd.c b/pam_umotd/pam_umotd.c
index 2fea67c..008e87b 100644
--- a/pam_umotd/pam_umotd.c
+++ b/pam_umotd/pam_umotd.c
@@ -337,38 +337,57 @@ pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
}
if (motd_file_name) {
char *file;
slist = gray_slist_create();
- gray_expand_string(pamh, motd_file_name, slist);
- gray_slist_append_char(slist, 0);
- file = gray_slist_finish(slist);
- retval = read_file(pamh, file);
+ if (!slist)
+ retval = errno_to_pam(errno);
+ else {
+ gray_expand_string(pamh, motd_file_name, slist);
+ gray_slist_append_char(slist, 0);
+ file = gray_slist_finish(slist);
+ if (file)
+ retval = read_file(pamh, file);
+ else
+ retval = errno_to_pam(errno);
+ }
gray_slist_free(&slist);
} else if (optindex >= 0) {
- int i;
char **xargv;
-
+
argc -= optindex;
argv += optindex;
if (!argc) {
_pam_log(LOG_INFO, "empty command line");
return retval;
}
- xargv = gray_malloc((argc + 1) * sizeof (xargv[0]));
+ xargv = calloc((argc + 1), sizeof (xargv[0]));
+ if (!xargv)
+ return errno_to_pam(errno);
slist = gray_slist_create();
- for (i = 0; i < argc; i++) {
- gray_expand_string(pamh, argv[i], slist);
- gray_slist_append_char(slist, 0);
- xargv[i] = gray_slist_finish(slist);
+ if (!slist)
+ retval = errno_to_pam(errno);
+ else {
+ int i;
+ int ec;
+
+ for (i = 0; i < argc; i++) {
+ gray_expand_string(pamh, argv[i], slist);
+ gray_slist_append_char(slist, 0);
+ xargv[i] = gray_slist_finish(slist);
+ }
+ xargv[i] = NULL;
+ ec = gray_slist_err(slist);
+ if (ec)
+ retval = errno_to_pam(ec);
+ else
+ retval = exec_file(pamh, xargv, logfile_name);
+ free(xargv);
+ gray_slist_free(&slist);
}
- xargv[i] = NULL;
- retval = exec_file(pamh, xargv, logfile_name);
- free(xargv);
- gray_slist_free(&slist);
} else
_pam_log(LOG_ERR,
"invalid usage: either file or exec must be specified");
return retval;
}

Return to:

Send suggestions and report system problems to the System administrator.