Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib/safe-mkdir.c @ 9658:8ba4253adc9b HEAD tip
*-login: SSL connections didn't get closed when the client got destroyed.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 08 May 2014 16:41:29 +0300 |
parents | 00cd9aacd03c |
children |
rev | line source |
---|---|
9532
00cd9aacd03c
Updated copyright notices to include year 2010.
Timo Sirainen <tss@iki.fi>
parents:
8590
diff
changeset
|
1 /* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */ |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
2 |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
3 #include "lib.h" |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
4 #include "safe-mkdir.h" |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
5 |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
6 #include <sys/stat.h> |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
7 #include <unistd.h> |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
8 #include <fcntl.h> |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
9 |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
10 int safe_mkdir(const char *dir, mode_t mode, uid_t uid, gid_t gid) |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
11 { |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
12 struct stat st; |
4457
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
13 int fd, ret = 2, changed_ret = 0; |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
14 |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
15 if (lstat(dir, &st) < 0) { |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
16 if (errno != ENOENT) |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
17 i_fatal("lstat() failed for %s: %m", dir); |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
18 |
4457
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
19 if (mkdir(dir, mode) < 0) { |
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
20 if (errno != EEXIST) |
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
21 i_fatal("Can't create directory %s: %m", dir); |
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
22 } else { |
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
23 /* created it */ |
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
24 ret = changed_ret = 1; |
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
25 } |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
26 } |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
27 |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
28 /* use fchown() and fchmod() just to make sure we aren't following |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
29 symbolic links. */ |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
30 fd = open(dir, O_RDONLY); |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
31 if (fd == -1) |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
32 i_fatal("open() failed for %s: %m", dir); |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
33 |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
34 if (fstat(fd, &st) < 0) |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
35 i_fatal("fstat() failed for %s: %m", dir); |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
36 |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
37 if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)) |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
38 i_fatal("Not a directory %s", dir); |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
39 |
1742
05427d8112ee
comment updates. it's not possible to change the file mode if you're not the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
40 /* change the file owner first, since it's the only user one who |
05427d8112ee
comment updates. it's not possible to change the file mode if you're not the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
41 can mess up with the file mode. */ |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
42 if (st.st_uid != uid || st.st_gid != gid) { |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
43 if (fchown(fd, uid, gid) < 0) |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
44 i_fatal("fchown() failed for %s: %m", dir); |
4457
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
45 ret = changed_ret; |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
46 } |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
47 |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
48 if ((st.st_mode & 07777) != mode) { |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
49 if (fchmod(fd, mode) < 0) |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
50 i_fatal("chmod() failed for %s: %m", dir); |
4457
fa7353daa44f
safe_mkdir() should return 1 always when it creates a new directory, even if
Timo Sirainen <tss@iki.fi>
parents:
1742
diff
changeset
|
51 ret = changed_ret; |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
52 } |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
53 |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
54 if (close(fd) < 0) |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
55 i_fatal("close() failed for %s: %m", dir); |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
56 |
1742
05427d8112ee
comment updates. it's not possible to change the file mode if you're not the
Timo Sirainen <tss@iki.fi>
parents:
1741
diff
changeset
|
57 /* paranoia: make sure we succeeded in everything. */ |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
58 if (lstat(dir, &st) < 0) |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
59 i_fatal("lstat() check failed for %s: %m", dir); |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
60 |
1263
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
61 if (!S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)) |
500ec0ec3b85
safe_mkdir(): usage fchmod() and fchown(). chmod() wasn't really safe and
Timo Sirainen <tss@iki.fi>
parents:
823
diff
changeset
|
62 i_fatal("Not a directory %s", dir); |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
63 |
823
d00ce0e4de7f
Whops, should have tested it :) Mode check always failed.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
64 if ((st.st_mode & 07777) != mode) { |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
65 i_fatal("safe_mkdir() failed: %s (%o) is still not mode %o", |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
66 dir, (int)st.st_mode, (int)mode); |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
67 } |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
68 if (st.st_uid != uid || st.st_gid != gid) { |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
69 i_fatal("safe_mkdir() failed: %s (%s, %s) " |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
70 "is still not owned by %s.%s", |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
71 dir, dec2str(st.st_uid), dec2str(st.st_gid), |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
72 dec2str(uid), dec2str(gid)); |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
73 } |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
74 |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
75 return ret; |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
diff
changeset
|
76 } |