mirror of
git://git.gnu.org.ua/pam-modules.git
synced 2025-04-26 00:19:52 +03:00
263 lines
5 KiB
C
263 lines
5 KiB
C
/* This file is part of pam-modules.
|
|
Copyright (C) 2008-2022 Sergey Poznyakoff
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation; either version 3 of the License, or (at your
|
|
option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
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>
|
|
|
|
char *
|
|
gray_env_get(struct gray_env *env, const char *name)
|
|
{
|
|
for (; env; env = env->next)
|
|
if (strcmp(env->name, name) == 0)
|
|
return env->value;
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
gray_env_get_bool(struct gray_env *env, const char *name, int dfl)
|
|
{
|
|
char *p = gray_env_get(env, name);
|
|
if (!p)
|
|
return dfl;
|
|
return gray_boolean_true_p(p);
|
|
}
|
|
|
|
void
|
|
gray_env_free(struct gray_env *env)
|
|
{
|
|
while (env) {
|
|
struct gray_env *next = env->next;
|
|
free(env->name);
|
|
free(env);
|
|
env = next;
|
|
}
|
|
}
|
|
|
|
static void
|
|
tr(char *input, char **map)
|
|
{
|
|
unsigned char *s = (unsigned char*) input;
|
|
|
|
for (; *s; s++) {
|
|
unsigned char *f = (unsigned char *)map[0];
|
|
unsigned char *t = (unsigned char *)map[1];
|
|
for (; *f && *t; f++, t++) {
|
|
if (f > (unsigned char *)map[0]
|
|
&& *f == '-' && *t == '-'
|
|
&& f[1] && t[1]) {
|
|
int a = f[-1];
|
|
int d = f[1] - a;
|
|
|
|
if ((d > 0
|
|
&& a < *s && *s <= a + d)
|
|
|| (d < 0
|
|
&& (a + d <= *s && *s < a))) {
|
|
*s = t[-1] + *s - a;
|
|
break;
|
|
}
|
|
++f; ++t;
|
|
} else if (*f == *s) {
|
|
*s = *t;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap)
|
|
{
|
|
FILE *fp;
|
|
char *p;
|
|
int rc = 0;
|
|
int line = 0;
|
|
char buf[128];
|
|
gray_slist_t slist = NULL;
|
|
struct gray_env *config_env = NULL;
|
|
|
|
fp = fopen(file_name, "r");
|
|
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))) {
|
|
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) {
|
|
slist = gray_slist_create();
|
|
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;
|
|
}
|
|
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);
|
|
|
|
if (*p == 0 || *p == '#')
|
|
continue;
|
|
|
|
if (p[len-1] == '\\') {
|
|
int err = 0;
|
|
|
|
/* Collect continuation lines */
|
|
if (!slist) {
|
|
slist = gray_slist_create();
|
|
if (!slist) {
|
|
rc = errno;
|
|
break;
|
|
}
|
|
}
|
|
do {
|
|
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)
|
|
break;
|
|
if (p[len-1] != '\n') {
|
|
_pam_log(LOG_EMERG,
|
|
"%s:%d: string too long",
|
|
file_name, line);
|
|
err = 1;
|
|
break;
|
|
}
|
|
p[len-1] = 0;
|
|
len = gray_trim_ws(p);
|
|
} while (p[len-1] == '\\');
|
|
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) {
|
|
rc = errno;
|
|
break;
|
|
}
|
|
|
|
env->name = strdup(p);
|
|
if (!env->name) {
|
|
rc = errno;
|
|
free(env);
|
|
break;
|
|
}
|
|
|
|
for (p = env->name; *p && !isspace(*p); p++)
|
|
;
|
|
if (*p)
|
|
*p++ = 0;
|
|
if (trmap)
|
|
tr(env->name, trmap);
|
|
for (; *p && isspace(*p); p++)
|
|
;
|
|
if (!*p) {
|
|
_pam_log(LOG_EMERG, "%s:%d: not enough fields",
|
|
file_name, line);
|
|
free(env->name);
|
|
free(env);
|
|
continue;
|
|
}
|
|
env->value = p;
|
|
env->next = config_env;
|
|
config_env = env;
|
|
}
|
|
|
|
gray_slist_free(&slist);
|
|
fclose(fp);
|
|
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)
|
|
{
|
|
return gray_env_read_tr(file_name, penv, NULL);
|
|
}
|
|
|
|
void
|
|
gray_env_merge(struct gray_env **pa, struct gray_env **pb)
|
|
{
|
|
if (!*pa)
|
|
*pa = *pb;
|
|
else if (!*pb)
|
|
return;
|
|
else {
|
|
struct gray_env *a;
|
|
for (a = *pa; a->next; a = a->next)
|
|
;
|
|
a->next = *pb;
|
|
}
|
|
*pb = NULL;
|
|
}
|
|
|
|
int
|
|
gray_boolean_true_p(const char *value)
|
|
{
|
|
return strcmp(value, "yes") == 0
|
|
|| strcmp(value, "true") == 0
|
|
|| strcmp(value, "t") == 0;
|
|
}
|
|
|