View | Details | Raw Unified | Return to bug 1348 | Differences between
and this patch

Collapse All | Expand All

(-)auth-rsa.c (-20 / +2 lines)
Lines 173-179 Link Here
173
	u_int bits;
173
	u_int bits;
174
	FILE *f;
174
	FILE *f;
175
	u_long linenum = 0;
175
	u_long linenum = 0;
176
	struct stat st;
177
	Key *key;
176
	Key *key;
178
177
179
	/* Temporarily use the user's uid. */
178
	/* Temporarily use the user's uid. */
Lines 183-208 Link Here
183
	file = authorized_keys_file(pw);
182
	file = authorized_keys_file(pw);
184
	debug("trying public RSA key file %s", file);
183
	debug("trying public RSA key file %s", file);
185
184
186
	/* Fail quietly if file does not exist */
185
	f = open_keyfile(file, pw, options.strict_modes);
187
	if (stat(file, &st) < 0) {
188
		/* Restore the privileged uid. */
189
		restore_uid();
190
		xfree(file);
191
		return (0);
192
	}
193
	/* Open the file containing the authorized keys. */
194
	f = fopen(file, "r");
195
	if (!f) {
186
	if (!f) {
196
		/* Restore the privileged uid. */
187
		xfree(file);
197
		restore_uid();
198
		xfree(file);
199
		return (0);
200
	}
201
	if (options.strict_modes &&
202
	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
203
		xfree(file);
204
		fclose(f);
205
		logit("Authentication refused: %s", line);
206
		restore_uid();
188
		restore_uid();
207
		return (0);
189
		return (0);
208
	}
190
	}
(-)auth.c (-73 lines)
Lines 397-475 Link Here
397
	return host_status;
397
	return host_status;
398
}
398
}
399
399
400
401
/*
402
 * Check a given file for security. This is defined as all components
403
 * of the path to the file must be owned by either the owner of
404
 * of the file or root and no directories must be group or world writable.
405
 *
406
 * XXX Should any specific check be done for sym links ?
407
 *
408
 * Takes an open file descriptor, the file name, a uid and and
409
 * error buffer plus max size as arguments.
410
 *
411
 * Returns 0 on success and -1 on failure
412
 */
413
int
414
secure_filename(FILE *f, const char *file, struct passwd *pw,
415
    char *err, size_t errlen)
416
{
417
	uid_t uid = pw->pw_uid;
418
	char buf[MAXPATHLEN], homedir[MAXPATHLEN];
419
	char *cp;
420
	int comparehome = 0;
421
	struct stat st;
422
423
	if (realpath(file, buf) == NULL) {
424
		snprintf(err, errlen, "realpath %s failed: %s", file,
425
		    strerror(errno));
426
		return -1;
427
	}
428
	if (realpath(pw->pw_dir, homedir) != NULL)
429
		comparehome = 1;
430
431
	/* check the open file to avoid races */
432
	if (fstat(fileno(f), &st) < 0 ||
433
	    (st.st_uid != 0 && st.st_uid != uid) ||
434
	    (st.st_mode & 022) != 0) {
435
		snprintf(err, errlen, "bad ownership or modes for file %s",
436
		    buf);
437
		return -1;
438
	}
439
440
	/* for each component of the canonical path, walking upwards */
441
	for (;;) {
442
		if ((cp = dirname(buf)) == NULL) {
443
			snprintf(err, errlen, "dirname() failed");
444
			return -1;
445
		}
446
		strlcpy(buf, cp, sizeof(buf));
447
448
		debug3("secure_filename: checking '%s'", buf);
449
		if (stat(buf, &st) < 0 ||
450
		    (st.st_uid != 0 && st.st_uid != uid) ||
451
		    (st.st_mode & 022) != 0) {
452
			snprintf(err, errlen,
453
			    "bad ownership or modes for directory %s", buf);
454
			return -1;
455
		}
456
457
		/* If are passed the homedir then we can stop */
458
		if (comparehome && strcmp(homedir, buf) == 0) {
459
			debug3("secure_filename: terminating check at '%s'",
460
			    buf);
461
			break;
462
		}
463
		/*
464
		 * dirname should always complete with a "/" path,
465
		 * but we can be paranoid and check for "." too
466
		 */
467
		if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
468
			break;
469
	}
470
	return 0;
471
}
472
473
struct passwd *
400
struct passwd *
474
getpwnamallow(const char *user)
401
getpwnamallow(const char *user)
475
{
402
{
(-)auth.h (-2 lines)
Lines 166-173 Link Here
166
char	*authorized_keys_file(struct passwd *);
166
char	*authorized_keys_file(struct passwd *);
167
char	*authorized_keys_file2(struct passwd *);
167
char	*authorized_keys_file2(struct passwd *);
168
168
169
int
170
secure_filename(FILE *, const char *, struct passwd *, char *, size_t);
171
169
172
HostStatus
170
HostStatus
173
check_key_in_hostfiles(struct passwd *, Key *, const char *,
171
check_key_in_hostfiles(struct passwd *, Key *, const char *,
(-)auth2-pubkey.c (-19 / +6 lines)
Lines 183-216 Link Here
183
	int found_key = 0;
183
	int found_key = 0;
184
	FILE *f;
184
	FILE *f;
185
	u_long linenum = 0;
185
	u_long linenum = 0;
186
	struct stat st;
187
	Key *found;
186
	Key *found;
188
	char *fp;
187
	char *fp;
189
188
190
	/* Temporarily use the user's uid. */
189
	/* Temporarily use the user's uid. */
191
	temporarily_use_uid(pw);
190
	temporarily_use_uid(pw);
192
191
192
	/* The authorized keys. */
193
	file = authorized_keys_file(pw);
193
	debug("trying public key file %s", file);
194
	debug("trying public key file %s", file);
194
195
195
	/* Fail quietly if file does not exist */
196
	f = open_keyfile(file, pw, options.strict_modes);
196
	if (stat(file, &st) < 0) {
197
		/* Restore the privileged uid. */
198
		restore_uid();
199
		return 0;
200
	}
201
	/* Open the file containing the authorized keys. */
202
	f = fopen(file, "r");
203
	if (!f) {
197
	if (!f) {
204
		/* Restore the privileged uid. */
198
		xfree(file);
205
		restore_uid();
199
		restore_uid();
206
		return 0;
200
		return (0);
207
	}
208
	if (options.strict_modes &&
209
	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
210
		fclose(f);
211
		logit("Authentication refused: %s", line);
212
		restore_uid();
213
		return 0;
214
	}
201
	}
215
202
216
	found_key = 0;
203
	found_key = 0;
(-)misc.c (+99 lines)
Lines 46-51 Link Here
46
# include <paths.h>
46
# include <paths.h>
47
#include <pwd.h>
47
#include <pwd.h>
48
#endif
48
#endif
49
#ifdef HAVE_LIBGEN_H
50
#include <libgen.h>
51
#endif
49
#ifdef SSH_TUN_OPENBSD
52
#ifdef SSH_TUN_OPENBSD
50
#include <net/if.h>
53
#include <net/if.h>
51
#endif
54
#endif
Lines 608-613 Link Here
608
}
611
}
609
612
610
/*
613
/*
614
 * Check a given file for security. This is defined as all components
615
 * of the path to the file must be owned by either the owner of
616
 * of the file or root and no directories must be group or world writable.
617
 *
618
 * XXX Should any specific check be done for sym links ?
619
 *
620
 * Takes an open file descriptor, the file name, a uid and and
621
 * error buffer plus max size as arguments.
622
 *
623
 * Returns 0 on success and -1 on failure
624
 */
625
static int
626
secure_filename(FILE *f, const char *file, struct passwd *pw,
627
    char *err, size_t errlen)
628
{
629
	uid_t uid = pw->pw_uid;
630
	char buf[MAXPATHLEN], homedir[MAXPATHLEN];
631
	char *cp;
632
	int comparehome = 0;
633
	struct stat st;
634
635
	if (realpath(file, buf) == NULL) {
636
		snprintf(err, errlen, "realpath %s failed: %s", file,
637
		    strerror(errno));
638
		return -1;
639
	}
640
	if (realpath(pw->pw_dir, homedir) != NULL)
641
		comparehome = 1;
642
643
	/* check the open file to avoid races */
644
	if (fstat(fileno(f), &st) < 0 ||
645
	    (st.st_uid != 0 && st.st_uid != uid) ||
646
	    (st.st_mode & 022) != 0) {
647
		snprintf(err, errlen, "bad ownership or modes for file %s",
648
		    buf);
649
		return -1;
650
	}
651
652
	/* for each component of the canonical path, walking upwards */
653
	for (;;) {
654
		if ((cp = dirname(buf)) == NULL) {
655
			snprintf(err, errlen, "dirname() failed");
656
			return -1;
657
		}
658
		strlcpy(buf, cp, sizeof(buf));
659
660
		debug3("secure_filename: checking '%s'", buf);
661
		if (stat(buf, &st) < 0 ||
662
		    (st.st_uid != 0 && st.st_uid != uid) ||
663
		    (st.st_mode & 022) != 0) {
664
			snprintf(err, errlen,
665
			    "bad ownership or modes for directory %s", buf);
666
			return -1;
667
		}
668
669
		/* If are passed the homedir then we can stop */
670
		if (comparehome && strcmp(homedir, buf) == 0) {
671
			debug3("secure_filename: terminating check at '%s'",
672
			    buf);
673
			break;
674
		}
675
		/*
676
		 * dirname should always complete with a "/" path,
677
		 * but we can be paranoid and check for "." too
678
		 */
679
		if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
680
			break;
681
	}
682
	return 0;
683
}
684
685
FILE *
686
open_keyfile(const char *filename, struct passwd *pw, int strict_modes)
687
{
688
	char err[1024];
689
	struct stat st;
690
	FILE *f;
691
692
	if (stat(filename, &st) < 0)
693
		return NULL;
694
695
	f = fopen(filename, "r");
696
	if (!f)
697
		return NULL;
698
699
	if (strict_modes &&
700
	    secure_filename(f, filename, pw, err, sizeof(err)) != 0) {
701
		fclose(f);
702
		logit("Authentication refused: %s", err);
703
		return NULL;
704
	}
705
706
	return f;
707
}
708
709
/*
611
 * Read an entire line from a public key file into a static buffer, discarding
710
 * Read an entire line from a public key file into a static buffer, discarding
612
 * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
711
 * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
613
 */
712
 */
(-)misc.h (+1 lines)
Lines 85-90 Link Here
85
85
86
char	*read_passphrase(const char *, int);
86
char	*read_passphrase(const char *, int);
87
int	 ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
87
int	 ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
88
FILE	*open_keyfile(const char *, struct passwd *, int);
88
int	 read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
89
int	 read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
89
90
90
#endif /* _MISC_H */
91
#endif /* _MISC_H */

Return to bug 1348