summaryrefslogtreecommitdiff
path: root/auth.c
diff options
context:
space:
mode:
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 1f976eee2..07e5b8f05 100644
--- a/auth.c
+++ b/auth.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $"); 26RCSID("$OpenBSD: auth.c,v 1.22 2001/05/20 17:20:35 markus Exp $");
27 27
28#ifdef HAVE_LOGIN_H 28#ifdef HAVE_LOGIN_H
29#include <login.h> 29#include <login.h>
@@ -32,6 +32,8 @@ RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
32#include <shadow.h> 32#include <shadow.h>
33#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */ 33#endif /* defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) */
34 34
35#include <libgen.h>
36
35#include "xmalloc.h" 37#include "xmalloc.h"
36#include "match.h" 38#include "match.h"
37#include "groupaccess.h" 39#include "groupaccess.h"
@@ -40,6 +42,8 @@ RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
40#include "auth.h" 42#include "auth.h"
41#include "auth-options.h" 43#include "auth-options.h"
42#include "canohost.h" 44#include "canohost.h"
45#include "buffer.h"
46#include "bufaux.h"
43 47
44/* import */ 48/* import */
45extern ServerOptions options; 49extern ServerOptions options;
@@ -222,3 +226,132 @@ auth_root_allowed(char *method)
222 log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); 226 log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
223 return 0; 227 return 0;
224} 228}
229
230
231/*
232 * Given a template and a passwd structure, build a filename
233 * by substituting % tokenised options. Currently, %% becomes '%',
234 * %h becomes the home directory and %u the username.
235 *
236 * This returns a buffer allocated by xmalloc.
237 */
238char *
239expand_filename(const char *filename, struct passwd *pw)
240{
241 Buffer buffer;
242 char *file;
243 const char *cp;
244
245 /*
246 * Build the filename string in the buffer by making the appropriate
247 * substitutions to the given file name.
248 */
249 buffer_init(&buffer);
250 for (cp = filename; *cp; cp++) {
251 if (cp[0] == '%' && cp[1] == '%') {
252 buffer_append(&buffer, "%", 1);
253 cp++;
254 continue;
255 }
256 if (cp[0] == '%' && cp[1] == 'h') {
257 buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir));
258 cp++;
259 continue;
260 }
261 if (cp[0] == '%' && cp[1] == 'u') {
262 buffer_append(&buffer, pw->pw_name,
263 strlen(pw->pw_name));
264 cp++;
265 continue;
266 }
267 buffer_append(&buffer, cp, 1);
268 }
269 buffer_append(&buffer, "\0", 1);
270
271 /*
272 * Ensure that filename starts anchored. If not, be backward
273 * compatible and prepend the '%h/'
274 */
275 file = xmalloc(MAXPATHLEN);
276 cp = buffer_ptr(&buffer);
277 if (*cp != '/')
278 snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp);
279 else
280 strlcpy(file, cp, MAXPATHLEN);
281
282 buffer_free(&buffer);
283 return file;
284}
285
286char *
287authorized_keys_file(struct passwd *pw)
288{
289 return expand_filename(options.authorized_keys_file, pw);
290}
291
292char *
293authorized_keys_file2(struct passwd *pw)
294{
295 return expand_filename(options.authorized_keys_file2, pw);
296}
297
298/*
299 * Check a given file for security. This is defined as all components
300 * of the path to the file must either be owned by either the owner of
301 * of the file or root and no directories must be world writable.
302 *
303 * XXX Should any specific check be done for sym links ?
304 *
305 * Takes an open file descriptor, the file name, a uid and and
306 * error buffer plus max size as arguments.
307 *
308 * Returns 0 on success and -1 on failure
309 */
310int
311secure_filename(FILE *f, const char *file, uid_t uid, char *err, size_t errlen)
312{
313 char buf[MAXPATHLEN];
314 char *cp;
315 struct stat st;
316
317 if (realpath(file, buf) == NULL) {
318 snprintf(err, errlen, "realpath %s failed: %s", file,
319 strerror(errno));
320 return -1;
321 }
322
323 /* check the open file to avoid races */
324 if (fstat(fileno(f), &st) < 0 ||
325 (st.st_uid != 0 && st.st_uid != uid) ||
326 (st.st_mode & 022) != 0) {
327 snprintf(err, errlen, "bad ownership or modes for file %s",
328 buf);
329 return -1;
330 }
331
332 /* for each component of the canonical path, walking upwards */
333 for (;;) {
334 if ((cp = dirname(buf)) == NULL) {
335 snprintf(err, errlen, "dirname() failed");
336 return -1;
337 }
338 strlcpy(buf, cp, sizeof(buf));
339
340 debug3("secure_filename: checking '%s'", buf);
341 if (stat(buf, &st) < 0 ||
342 (st.st_uid != 0 && st.st_uid != uid) ||
343 (st.st_mode & 022) != 0) {
344 snprintf(err, errlen,
345 "bad ownership or modes for directory %s", buf);
346 return -1;
347 }
348
349 /*
350 * dirname should always complete with a "/" path,
351 * but we can be paranoid and check for "." too
352 */
353 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
354 break;
355 }
356 return 0;
357}