pam-modules/lib/vartab.c
Sergey Poznyakoff a8eb15d394 Update copyright years
git-svn-id: file:///svnroot/pam-modules/trunk@113 56984be4-0537-0410-a56c-fcb268c96130
2011-04-08 08:54:48 +00:00

201 lines
4 KiB
C

/* This file is part of pam-modules.
Copyright (C) 2009-2011 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>
struct keyword *
gray_find_keyword(struct keyword *kwtab, const char *str, size_t len)
{
for (; kwtab->name; kwtab++)
if (kwtab->len == len
&& strncmp(kwtab->name, str, kwtab->len) == 0)
return kwtab;
return NULL;
}
static struct keyword vartab[] = {
DCL("service", PAM_SERVICE),
DCL("user", PAM_USER),
DCL("tty", PAM_TTY),
DCL("rhost", PAM_RHOST),
DCL("ruser", PAM_RUSER),
DCL("prompt", PAM_USER_PROMPT),
DCL("password", PAM_AUTHTOK),
{ NULL }
};
static int
var_tok(const char *str, const char ** pvar, size_t *plen)
{
size_t len;
for (len = 0; str[len]; len++) {
if (str[len] == '}' || str[len] == ':') {
*pvar = str;
*plen = len;
return 0;
}
}
return 1;
}
static int
repl_tok(const char *str, const char ** pret, size_t *plen)
{
size_t len;
for (len = 0; str[len]; len++) {
if (str[len] == '}') {
*pret = str;
*plen = len;
return 0;
}
}
return 1;
}
#define ISKW(c) ((c) && (isalnum(c) || (c) == '_'))
static int
get_variable(pam_handle_t *pamh, const char *str, gray_slist_t slist,
const char **endp)
{
const char *name;
size_t namelen;
const char *repl = NULL;
size_t repllen = 0;
const char *val;
size_t vallen;
struct keyword *kw;
const char *end;
int rc;
str++; /* Get past the initial $ */
if (*str == '{') {
str++;
if (var_tok(str, &name, &namelen))
return 1;
end = str + namelen;
if (*end == ':') {
end++;
if (*end == '-')
end++;
if (repl_tok(end, &repl, &repllen))
return 1;
end += repllen;
}
end++;
} else {
name = end = str;
for (namelen = 0; ISKW(*end); namelen++, end++)
;
}
kw = gray_find_keyword(vartab, name, namelen);
if (!kw) {
_pam_log(LOG_ERR,
"unknown PAM variable: %*.*s",
namelen, namelen, name);
return 1;
}
rc = pam_get_item(pamh, kw->code, (const void**) &val);
if (rc) {
_pam_log(LOG_ERR,
"cannot obtain variable %s: %s",
kw->name, pam_strerror(pamh, rc));
return 1;
}
if (!val) {
if (repl) {
val = repl;
vallen = repllen;
} else {
val = "";
vallen = 0;
}
} else
vallen = strlen(val);
gray_escape_string(slist, val, vallen);
*endp = end;
return 0;
}
void
gray_expand_argv(pam_handle_t *pamh, int argc, const char **argv,
gray_slist_t slist)
{
int i;
for (i = 0; i < argc; i++) {
if (i > 0)
gray_slist_append_char(slist, ' ');
if (strchr(argv[i], '$') == 0)
gray_slist_append(slist, argv[i], strlen(argv[i]));
else {
const char *p;
for (p = argv[i]; *p; p++) {
if (*p == '\\') {
p++;
gray_slist_append_char(slist, *p);
} else if (*p == '$') {
if (get_variable(pamh, p, slist, &p))
gray_slist_append_char(slist,
*p);
else
p--;
} else
gray_slist_append_char(slist, *p);
}
}
}
}
void
gray_expand_string(pam_handle_t *pamh, const char *str, gray_slist_t slist)
{
const char *p;
#define FLUSH() gray_slist_append(slist, str, p - str); str = p
for (p = str; *p; ) {
if (*p == '\\') {
FLUSH();
p++;
if (*p) {
gray_slist_append_char(slist, *p);
p++;
} else {
gray_slist_append_char(slist, '\\');
break;
}
str = p;
} else if (*p == '$') {
FLUSH();
if (get_variable(pamh, p, slist, &p)) {
gray_slist_append_char(slist, *p);
p++;
}
str = p;
} else
p++;
}
FLUSH();
}