summaryrefslogtreecommitdiffstats
path: root/auth.c
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2001-06-05 20:25:05 +0000
committerBen Lindstrom <mouring@eviladmin.org>2001-06-05 20:25:05 +0000
commitbfb3a0e973214fabc1be744b8c7e4a89a0c5570c (patch)
tree8227151356ee10ae6762c42442f272b0db418973 /auth.c
parente2595448766a4149bbd2652830d1b086a066af13 (diff)
- markus@cvs.openbsd.org 2001/05/20 17:20:36
[auth-rsa.c auth.c auth.h auth2.c servconf.c servconf.h sshd.8 sshd_config] configurable authorized_keys{,2} location; originally from peter@; ok djm@
Diffstat (limited to 'auth.c')
-rw-r--r--auth.c135
1 files changed, 134 insertions, 1 deletions
diff --git a/auth.c b/auth.c
index 1f976eee..07e5b8f0 100644
--- a/auth.c
+++ b/auth.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
+RCSID("$OpenBSD: auth.c,v 1.22 2001/05/20 17:20:35 markus Exp $");
#ifdef HAVE_LOGIN_H
#include <login.h>
@@ -32,6 +32,8 @@ RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
#include <shadow.h>
#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
+#include <libgen.h>
+
#include "xmalloc.h"
#include "match.h"
#include "groupaccess.h"
@@ -40,6 +42,8 @@ RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
#include "auth.h"
#include "auth-options.h"
#include "canohost.h"
+#include "buffer.h"
+#include "bufaux.h"
/* import */
extern ServerOptions options;
@@ -222,3 +226,132 @@ auth_root_allowed(char *method)
log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
return 0;
}
+
+
+/*
+ * Given a template and a passwd structure, build a filename
+ * by substituting % tokenised options. Currently, %% becomes '%',
+ * %h becomes the home directory and %u the username.
+ *
+ * This returns a buffer allocated by xmalloc.
+ */
+char *
+expand_filename(const char *filename, struct passwd *pw)
+{
+ Buffer buffer;
+ char *file;
+ const char *cp;
+
+ /*
+ * Build the filename string in the buffer by making the appropriate
+ * substitutions to the given file name.
+ */
+ buffer_init(&buffer);
+ for (cp = filename; *cp; cp++) {
+ if (cp[0] == '%' && cp[1] == '%') {
+ buffer_append(&buffer, "%", 1);
+ cp++;
+ continue;
+ }
+ if (cp[0] == '%' && cp[1] == 'h') {
+ buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir));
+ cp++;
+ continue;
+ }
+ if (cp[0] == '%' && cp[1] == 'u') {
+ buffer_append(&buffer, pw->pw_name,
+ strlen(pw->pw_name));
+ cp++;
+ continue;
+ }
+ buffer_append(&buffer, cp, 1);
+ }
+ buffer_append(&buffer, "\0", 1);
+
+ /*
+ * Ensure that filename starts anchored. If not, be backward
+ * compatible and prepend the '%h/'
+ */
+ file = xmalloc(MAXPATHLEN);
+ cp = buffer_ptr(&buffer);
+ if (*cp != '/')
+ snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp);
+ else
+ strlcpy(file, cp, MAXPATHLEN);
+
+ buffer_free(&buffer);
+ return file;
+}
+
+char *
+authorized_keys_file(struct passwd *pw)
+{
+ return expand_filename(options.authorized_keys_file, pw);
+}
+
+char *
+authorized_keys_file2(struct passwd *pw)
+{
+ return expand_filename(options.authorized_keys_file2, pw);
+}
+
+/*
+ * Check a given file for security. This is defined as all components
+ * of the path to the file must either be owned by either the owner of
+ * of the file or root and no directories must be world writable.
+ *
+ * XXX Should any specific check be done for sym links ?
+ *
+ * Takes an open file descriptor, the file name, a uid and and
+ * error buffer plus max size as arguments.
+ *
+ * Returns 0 on success and -1 on failure
+ */
+int
+secure_filename(FILE *f, const char *file, uid_t uid, char *err, size_t errlen)
+{
+ char buf[MAXPATHLEN];
+ char *cp;
+ struct stat st;
+
+ if (realpath(file, buf) == NULL) {
+ snprintf(err, errlen, "realpath %s failed: %s", file,
+ strerror(errno));
+ return -1;
+ }
+
+ /* check the open file to avoid races */
+ if (fstat(fileno(f), &st) < 0 ||
+ (st.st_uid != 0 && st.st_uid != uid) ||
+ (st.st_mode & 022) != 0) {
+ snprintf(err, errlen, "bad ownership or modes for file %s",
+ buf);
+ return -1;
+ }
+
+ /* for each component of the canonical path, walking upwards */
+ for (;;) {
+ if ((cp = dirname(buf)) == NULL) {
+ snprintf(err, errlen, "dirname() failed");
+ return -1;
+ }
+ strlcpy(buf, cp, sizeof(buf));
+
+ debug3("secure_filename: checking '%s'", buf);
+ if (stat(buf, &st) < 0 ||
+ (st.st_uid != 0 && st.st_uid != uid) ||
+ (st.st_mode & 022) != 0) {
+ snprintf(err, errlen,
+ "bad ownership or modes for directory %s", buf);
+ return -1;
+ }
+
+ /*
+ * dirname should always complete with a "/" path,
+ * but we can be paranoid and check for "." too
+ */
+ if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
+ break;
+ }
+ return 0;
+}