summaryrefslogtreecommitdiff
path: root/lib/libc/gen
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-08-10 15:53:32 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-08-10 15:53:32 +0000
commite6aea2c186d9eef5275040b69b69d4764a29f5b8 (patch)
tree4f5a815157f2ffb0d4196ef9193edf7201538919 /lib/libc/gen
parentc718bcb3bd69dcc25b0f8b5c0b636ea704963c21 (diff)
Only expand a tilde for strings like "~", "~/..", "~user" and "~user/".
For the PATH, only expand a tilde that is at the beginning of the path name. This is similar to the behavior prior to my commit here yesterday.
Diffstat (limited to 'lib/libc/gen')
-rw-r--r--lib/libc/gen/login_cap.c62
1 files changed, 43 insertions, 19 deletions
diff --git a/lib/libc/gen/login_cap.c b/lib/libc/gen/login_cap.c
index aef64066b87..a365810fa81 100644
--- a/lib/libc/gen/login_cap.c
+++ b/lib/libc/gen/login_cap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: login_cap.c,v 1.22 2004/08/09 21:15:09 millert Exp $ */
+/* $OpenBSD: login_cap.c,v 1.23 2004/08/10 15:53:31 millert Exp $ */
/*
* Copyright (c) 2000-2004 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -68,8 +68,8 @@
static char *_authtypes[] = { LOGIN_DEFSTYLE, 0 };
-static char *expandstr(const char *, const struct passwd *);
-static int login_setenv(char *, char *, const struct passwd *);
+static char *expandstr(const char *, const struct passwd *, int);
+static int login_setenv(char *, char *, const struct passwd *, int);
static int setuserenv(login_cap_t *lc, const struct passwd *pwd);
static int setuserpath(login_cap_t *, const struct passwd *pwd);
static u_quad_t multiply(u_quad_t, u_quad_t);
@@ -729,7 +729,7 @@ setuserpath(login_cap_t *lc, const struct passwd *pwd)
}
*np = '\0';
setit:
- error = login_setenv("PATH", path ? path : _PATH_DEFPATH, pwd);
+ error = login_setenv("PATH", path ? path : _PATH_DEFPATH, pwd, 1);
free(opath);
free(path);
return (error);
@@ -773,7 +773,7 @@ setuserenv(login_cap_t *lc, const struct passwd *pwd)
*value++ = '\0';
else
value = "";
- if ((error = login_setenv(beg, value, pwd)) != 0) {
+ if ((error = login_setenv(beg, value, pwd, 0)) != 0) {
free(list);
return (error);
}
@@ -787,13 +787,13 @@ setuserenv(login_cap_t *lc, const struct passwd *pwd)
* Set an environment variable, substituting for ~ and $
*/
static int
-login_setenv(char *name, char *ovalue, const struct passwd *pwd)
+login_setenv(char *name, char *ovalue, const struct passwd *pwd, int ispath)
{
char *value = NULL;
int error;
if (*ovalue != '\0')
- value = expandstr(ovalue, pwd);
+ value = expandstr(ovalue, pwd, ispath);
error = setenv(name, value ? value : ovalue, 1);
free(value);
return (error);
@@ -1006,28 +1006,49 @@ secure_path(char *path)
}
/*
+ * Check whether or not a tilde in a string should be expanded.
+ * We only do expansion for things like "~", "~/...", ~me", "~me/...".
+ * Additionally, for paths the tilde must be a the beginning.
+ */
+#define tilde_valid(s, b, u, l, ip) \
+ ((!(ip) || (s) == (b) || (s)[-1] == ':') && \
+ ((s)[1] == '/' || (s)[1] == '\0' || \
+ (strncmp((s)+1, u, l) == 0 && ((s)[l+1] == '/' || (s)[l+1] == '\0'))))
+
+/*
* Make a copy of a string, expanding '~' to the user's homedir, '$' to the
* login name and other escape sequences as per cgetstr(3).
*/
static char *
-expandstr(const char *ostr, const struct passwd *pwd)
+expandstr(const char *ostr, const struct passwd *pwd, int ispath)
{
- size_t n, olen, nlen;
+ size_t n, olen, nlen, ulen, dlen;
const char *ep, *eo, *op;
char *nstr, *np;
int ch;
+ if (pwd != NULL) {
+ ulen = strlen(pwd->pw_name);
+ dlen = strlen(pwd->pw_dir);
+ }
+
/* calculate the size of the new string */
olen = nlen = strlen(ostr);
for (op = ostr, ep = ostr + olen; op < ep; op++) {
switch (*op) {
case '~':
- if (pwd != NULL)
- nlen += strlen(pwd->pw_dir) - 1;
+ if (pwd == NULL ||
+ !tilde_valid(op, ostr, pwd->pw_name, ulen, ispath))
+ break;
+ if (op[1] != '/' && op[1] != '\0') {
+ op += ulen; /* ~username */
+ nlen = nlen - ulen - 1 + dlen;
+ } else
+ nlen += dlen - 1;
break;
case '$':
if (pwd != NULL)
- nlen += strlen(pwd->pw_name) - 1;
+ nlen += ulen - 1;
break;
case '^':
/* control char */
@@ -1054,18 +1075,21 @@ expandstr(const char *ostr, const struct passwd *pwd)
for (op = ostr, ep = ostr + olen; op < ep; op++) {
switch ((ch = *op)) {
case '~':
- if (pwd == NULL)
+ if (pwd == NULL ||
+ !tilde_valid(op, ostr, pwd->pw_name, ulen, ispath))
break;
- n = strlcpy(np, pwd->pw_dir, nlen);
- nlen -= n;
- np += n;
+ if (op[1] != '/' && op[1] != '\0')
+ op += ulen; /* ~username */
+ strlcpy(np, pwd->pw_dir, nlen);
+ nlen -= dlen;
+ np += dlen;
continue;
case '$':
if (pwd == NULL)
break;
- n = strlcpy(np, pwd->pw_name, nlen);
- nlen -= n;
- np += n;
+ strlcpy(np, pwd->pw_name, nlen);
+ nlen -= ulen;
+ np += ulen;
continue;
case '^':
if (op[1] != '\0')