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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }