summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2019-12-04 06:25:46 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2019-12-04 06:25:46 +0000
commiteae003b59c6a4773f2f3c7d67381ace01a1ddca6 (patch)
treee59d8c2ac4508319aa6cd5ec78c43396527c5ce6 /lib
parentce0126e096657d7eb7a96a2e9807c5423ba1ed93 (diff)
libc's authentication privsep layer performed insufficient username
validation. Repair work mostly by markus and millert, first of all solving the primary problem, then adding some additional validation points. And then futher validation in login and su. This will be 6.5/021_libcauth.patch.sig and 6.6/010_libcauth.patch.sig Reported by Qualys
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/gen/auth_subr.c12
-rw-r--r--lib/libc/gen/authenticate.c37
2 files changed, 39 insertions, 10 deletions
diff --git a/lib/libc/gen/auth_subr.c b/lib/libc/gen/auth_subr.c
index 6d1844f4a28..1286a96fe40 100644
--- a/lib/libc/gen/auth_subr.c
+++ b/lib/libc/gen/auth_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth_subr.c,v 1.53 2019/06/28 13:32:41 deraadt Exp $ */
+/* $OpenBSD: auth_subr.c,v 1.54 2019/12/04 06:25:45 deraadt Exp $ */
/*
* Copyright (c) 2000-2002,2004 Todd C. Miller <millert@openbsd.org>
@@ -304,7 +304,8 @@ auth_challenge(auth_session_t *as)
char path[PATH_MAX];
int len;
- if (as == NULL || as->style == NULL || as->name == NULL)
+ if (as == NULL || as->style == NULL || as->name == NULL ||
+ !_auth_validuser(as->name))
return (NULL);
len = snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", as->style);
@@ -316,7 +317,7 @@ auth_challenge(auth_session_t *as)
free(as->challenge);
as->challenge = NULL;
- auth_call(as, path, as->style, "-s", "challenge", as->name,
+ auth_call(as, path, as->style, "-s", "challenge", "--", as->name,
as->class, (char *)NULL);
if (as->state & AUTH_CHALLENGE)
as->challenge = auth_getvalue(as, "challenge");
@@ -476,6 +477,10 @@ auth_setitem(auth_session_t *as, auth_item_t item, char *value)
case AUTHV_NAME:
if (value == as->name)
return (0);
+ if (value != NULL && !_auth_validuser(value)) {
+ errno = EINVAL;
+ return (-1);
+ }
if (value != NULL && (value = strdup(value)) == NULL)
return (-1);
free(as->name);
@@ -821,6 +826,7 @@ auth_call(auth_session_t *as, char *path, ...)
argv[argc++] = "-v";
argv[argc++] = "fd=4"; /* AUTH_FD, see below */
}
+ /* XXX - fail if out of space in argv */
for (opt = as->optlist; opt != NULL; opt = opt->next) {
if (argc < Nargc - 2) {
argv[argc++] = "-v";
diff --git a/lib/libc/gen/authenticate.c b/lib/libc/gen/authenticate.c
index fb96881832f..5fb6853888a 100644
--- a/lib/libc/gen/authenticate.c
+++ b/lib/libc/gen/authenticate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authenticate.c,v 1.27 2019/06/28 13:32:41 deraadt Exp $ */
+/* $OpenBSD: authenticate.c,v 1.28 2019/12/04 06:25:45 deraadt Exp $ */
/*-
* Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
@@ -174,6 +174,17 @@ auth_cat(char *file)
DEF_WEAK(auth_cat);
int
+_auth_validuser(const char *name)
+{
+ /* User name must be specified and may not start with a '-'. */
+ if (*name == '\0' || *name == '-') {
+ syslog(LOG_ERR, "invalid user name %s", name);
+ return 0;
+ }
+ return 1;
+}
+
+int
auth_approval(auth_session_t *as, login_cap_t *lc, char *name, char *type)
{
int close_on_exit, close_lc_on_exit, len;
@@ -192,6 +203,10 @@ auth_approval(auth_session_t *as, login_cap_t *lc, char *name, char *type)
if (pwd == NULL) {
if (name != NULL) {
+ if (!_auth_validuser(name)) {
+ warnx("cannot approve who we don't recognize");
+ return (0);
+ }
getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
} else {
getpwuid_r(getuid(), &pwstore, pwbuf, sizeof(pwbuf),
@@ -217,7 +232,7 @@ auth_approval(auth_session_t *as, login_cap_t *lc, char *name, char *type)
}
if (pwd == NULL && (approve = strchr(name, '.')) != NULL) {
strlcpy(path, name, sizeof path);
- path[approve-name] = '\0';
+ path[approve - name] = '\0';
getpwnam_r(name, &pwstore, pwbuf, sizeof(pwbuf), &pwd);
}
lc = login_getclass(pwd ? pwd->pw_class : NULL);
@@ -290,7 +305,7 @@ auth_approval(auth_session_t *as, login_cap_t *lc, char *name, char *type)
}
}
if (approve)
- auth_call(as, approve, strrchr(approve, '/') + 1, name,
+ auth_call(as, approve, strrchr(approve, '/') + 1, "--", name,
lc->lc_class, type, (char *)NULL);
out:
@@ -314,6 +329,8 @@ auth_usercheck(char *name, char *style, char *type, char *password)
struct passwd pwstore, *pwd = NULL;
char *slash;
+ if (!_auth_validuser(name))
+ return (NULL);
if (strlcpy(namebuf, name, sizeof(namebuf)) >= sizeof(namebuf))
return (NULL);
name = namebuf;
@@ -382,6 +399,8 @@ auth_userchallenge(char *name, char *style, char *type, char **challengep)
struct passwd pwstore, *pwd = NULL;
char *slash, pwbuf[_PW_BUF_LEN];
+ if (!_auth_validuser(name))
+ return (NULL);
if (strlen(name) >= sizeof(namebuf))
return (NULL);
strlcpy(namebuf, name, sizeof namebuf);
@@ -440,7 +459,8 @@ auth_userresponse(auth_session_t *as, char *response, int more)
auth_setstate(as, 0);
if ((style = auth_getitem(as, AUTHV_STYLE)) == NULL ||
- (name = auth_getitem(as, AUTHV_NAME)) == NULL) {
+ (name = auth_getitem(as, AUTHV_NAME)) == NULL ||
+ !_auth_validuser(name)) {
if (more == 0)
return (auth_close(as));
return(0);
@@ -466,7 +486,8 @@ auth_userresponse(auth_session_t *as, char *response, int more)
} else
auth_setdata(as, "", 1);
- auth_call(as, path, style, "-s", "response", name, class, (char *)NULL);
+ auth_call(as, path, style, "-s", "response", "--", name,
+ class, (char *)NULL);
/*
* If they authenticated then make sure they did not expire
@@ -495,7 +516,7 @@ auth_verify(auth_session_t *as, char *style, char *name, ...)
char path[PATH_MAX];
if ((name == NULL || style == NULL) && as == NULL)
- return (as);
+ return (NULL);
if (as == NULL && (as = auth_open()) == NULL)
return (NULL);
@@ -509,12 +530,14 @@ auth_verify(auth_session_t *as, char *style, char *name, ...)
style = auth_getitem(as, AUTHV_STYLE);
name = auth_getitem(as, AUTHV_NAME);
+ if (!_auth_validuser(name))
+ return (as);
snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
va_start(ap, name);
auth_set_va_list(as, ap);
auth_call(as, path, auth_getitem(as, AUTHV_STYLE), "-s",
- auth_getitem(as, AUTHV_SERVICE), name, (char *)NULL);
+ auth_getitem(as, AUTHV_SERVICE), "--", name, (char *)NULL);
va_end(ap);
return (as);
}