Added lock mode MU_LOCK_EXTERNAL which calls an external program to do
the locking. Default is "dotlock", which is setgid mail so can lock in a mailspool that users may not have write permissions to.
Showing
3 changed files
with
59 additions
and
12 deletions
... | @@ -20,16 +20,16 @@ | ... | @@ -20,16 +20,16 @@ |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #include <stdlib.h> | 22 | #include <stdlib.h> |
23 | #ifdef __EXT_QNX | ||
24 | # undef __EXT_QNX | ||
25 | #endif | ||
26 | #include <unistd.h> | ||
23 | 27 | ||
24 | #include <argp.h> | 28 | #include <argp.h> |
25 | 29 | ||
26 | #include <mailutils/errno.h> | 30 | #include <mailutils/errno.h> |
27 | #include <mailutils/locker.h> | 31 | #include <mailutils/locker.h> |
28 | 32 | ||
29 | #define MU_DL_EX_OK 0 | ||
30 | #define MU_DL_EX_ERROR 1 | ||
31 | #define MU_DL_EX_EXIST 3 | ||
32 | |||
33 | const char *argp_program_version = "GNU dotlock (" PACKAGE ") " VERSION; | 33 | const char *argp_program_version = "GNU dotlock (" PACKAGE ") " VERSION; |
34 | const char *argp_program_bug_address = "<bug-mailutils@gnu.org>"; | 34 | const char *argp_program_bug_address = "<bug-mailutils@gnu.org>"; |
35 | static char doc[] = | 35 | static char doc[] = |
... | @@ -54,6 +54,9 @@ static struct argp_option options[] = { | ... | @@ -54,6 +54,9 @@ static struct argp_option options[] = { |
54 | {"debug", 'd', NULL, 0, | 54 | {"debug", 'd', NULL, 0, |
55 | "Print details of failure reasons to stderr", 0}, | 55 | "Print details of failure reasons to stderr", 0}, |
56 | 56 | ||
57 | {"test", 'T', "PROGRAM", OPTION_HIDDEN, | ||
58 | "Test external dotlocker", 0}, | ||
59 | |||
57 | {NULL, 0, NULL, 0, NULL, 0} | 60 | {NULL, 0, NULL, 0, NULL, 0} |
58 | }; | 61 | }; |
59 | 62 | ||
... | @@ -72,6 +75,7 @@ static int flags; | ... | @@ -72,6 +75,7 @@ static int flags; |
72 | static int retries; | 75 | static int retries; |
73 | static int force; | 76 | static int force; |
74 | static int debug; | 77 | static int debug; |
78 | static const char *program; | ||
75 | 79 | ||
76 | static error_t | 80 | static error_t |
77 | parse_opt (int key, char *arg, struct argp_state *state) | 81 | parse_opt (int key, char *arg, struct argp_state *state) |
... | @@ -86,11 +90,18 @@ parse_opt (int key, char *arg, struct argp_state *state) | ... | @@ -86,11 +90,18 @@ parse_opt (int key, char *arg, struct argp_state *state) |
86 | unlock = 1; | 90 | unlock = 1; |
87 | break; | 91 | break; |
88 | 92 | ||
93 | case 'T': | ||
94 | /* This options exists only to test whether internal and external | ||
95 | locking work correctly/the same. */ | ||
96 | flags |= MU_LOCKER_EXTERNAL; | ||
97 | program = arg; | ||
98 | break; | ||
99 | |||
89 | case 'r': | 100 | case 'r': |
90 | if (arg) | 101 | if (arg) |
91 | { | 102 | { |
92 | retries = atoi (arg); | 103 | retries = atoi (arg); |
93 | if (retries == 0) | 104 | if (retries <= 0) |
94 | argp_error (state, "RETRIES must be greater than 0"); | 105 | argp_error (state, "RETRIES must be greater than 0"); |
95 | } | 106 | } |
96 | flags |= MU_LOCKER_RETRY; | 107 | flags |= MU_LOCKER_RETRY; |
... | @@ -100,7 +111,7 @@ parse_opt (int key, char *arg, struct argp_state *state) | ... | @@ -100,7 +111,7 @@ parse_opt (int key, char *arg, struct argp_state *state) |
100 | if (arg) | 111 | if (arg) |
101 | { | 112 | { |
102 | force = atoi (arg); | 113 | force = atoi (arg); |
103 | if (force == 0) | 114 | if (force <= 0) |
104 | argp_error (state, "MINUTES must be greater than 0"); | 115 | argp_error (state, "MINUTES must be greater than 0"); |
105 | force *= 60; | 116 | force *= 60; |
106 | } | 117 | } |
... | @@ -127,6 +138,13 @@ main (int argc, char *argv[]) | ... | @@ -127,6 +138,13 @@ main (int argc, char *argv[]) |
127 | { | 138 | { |
128 | locker_t locker = 0; | 139 | locker_t locker = 0; |
129 | int err = 0; | 140 | int err = 0; |
141 | pid_t usergid = getgid(); | ||
142 | pid_t mailgid = getegid(); | ||
143 | |||
144 | /* Drop permissions during argument parsing. */ | ||
145 | |||
146 | if(setegid(usergid) < 0) | ||
147 | return MU_DL_EX_ERROR; | ||
130 | 148 | ||
131 | argp_parse (&argp, argc, argv, 0, NULL, NULL); | 149 | argp_parse (&argp, argc, argv, 0, NULL, NULL); |
132 | 150 | ||
... | @@ -145,11 +163,19 @@ main (int argc, char *argv[]) | ... | @@ -145,11 +163,19 @@ main (int argc, char *argv[]) |
145 | if (retries != 0) | 163 | if (retries != 0) |
146 | locker_set_retries (locker, retries); | 164 | locker_set_retries (locker, retries); |
147 | 165 | ||
166 | if (program != 0) | ||
167 | locker_set_external (locker, program); | ||
168 | |||
169 | if(setegid(mailgid) < 0) | ||
170 | return MU_DL_EX_ERROR; | ||
171 | |||
148 | if (unlock) | 172 | if (unlock) |
149 | err = locker_remove_lock (locker); | 173 | err = locker_remove_lock (locker); |
150 | else | 174 | else |
151 | err = locker_lock (locker); | 175 | err = locker_lock (locker); |
152 | 176 | ||
177 | setegid(usergid); | ||
178 | |||
153 | locker_destroy (&locker); | 179 | locker_destroy (&locker); |
154 | 180 | ||
155 | if (debug && err) | 181 | if (debug && err) |
... | @@ -161,6 +187,12 @@ main (int argc, char *argv[]) | ... | @@ -161,6 +187,12 @@ main (int argc, char *argv[]) |
161 | case 0: | 187 | case 0: |
162 | err = MU_DL_EX_OK; | 188 | err = MU_DL_EX_OK; |
163 | break; | 189 | break; |
190 | case EPERM: | ||
191 | err = MU_DL_EX_PERM; | ||
192 | break; | ||
193 | case MU_ERR_LOCK_NOT_HELD: | ||
194 | err = MU_DL_EX_NEXIST; | ||
195 | break; | ||
164 | case MU_ERR_LOCK_CONFLICT: | 196 | case MU_ERR_LOCK_CONFLICT: |
165 | err = MU_DL_EX_EXIST; | 197 | err = MU_DL_EX_EXIST; |
166 | break; | 198 | break; |
... | @@ -171,3 +203,4 @@ main (int argc, char *argv[]) | ... | @@ -171,3 +203,4 @@ main (int argc, char *argv[]) |
171 | 203 | ||
172 | return err; | 204 | return err; |
173 | } | 205 | } |
206 | ... | ... |
... | @@ -18,11 +18,8 @@ | ... | @@ -18,11 +18,8 @@ |
18 | #ifndef _MAILUTILS_LOCKER_H | 18 | #ifndef _MAILUTILS_LOCKER_H |
19 | #define _MAILUTILS_LOCKER_H | 19 | #define _MAILUTILS_LOCKER_H |
20 | 20 | ||
21 | #include <mailutils/mu_features.h> | ||
22 | #include <mailutils/types.h> | 21 | #include <mailutils/types.h> |
23 | 22 | ||
24 | #include <sys/types.h> | ||
25 | |||
26 | #ifdef __cplusplus | 23 | #ifdef __cplusplus |
27 | extern "C" { | 24 | extern "C" { |
28 | #endif | 25 | #endif |
... | @@ -31,12 +28,20 @@ extern "C" { | ... | @@ -31,12 +28,20 @@ extern "C" { |
31 | #define MU_LOCKER_EXPIRE_TIME (10 * 60) | 28 | #define MU_LOCKER_EXPIRE_TIME (10 * 60) |
32 | #define MU_LOCKER_RETRIES (10) | 29 | #define MU_LOCKER_RETRIES (10) |
33 | #define MU_LOCKER_RETRY_SLEEP (1) | 30 | #define MU_LOCKER_RETRY_SLEEP (1) |
31 | #define MU_LOCKER_EXTERNAL_PROGRAM "dotlock" | ||
32 | |||
33 | /* return codes for the external locker */ | ||
34 | #define MU_DL_EX_PERM 4 /* insufficient permissions */ | ||
35 | #define MU_DL_EX_EXIST 3 /* lock requested, but file is already locked */ | ||
36 | #define MU_DL_EX_NEXIST 2 /* unlock requested, but file is not locked */ | ||
37 | #define MU_DL_EX_ERROR 1 /* failed due to some other error */ | ||
38 | #define MU_DL_EX_OK 0 /* success */ | ||
34 | 39 | ||
35 | /* locker_create() flags */ | 40 | /* locker_create() flags */ |
36 | 41 | ||
37 | #define MU_LOCKER_NULL 0 | 42 | #define MU_LOCKER_SIMPLE 0x00 |
38 | /* Special locker type: means no lock. This is to be used with | 43 | /* Just try and dotlock the file, not the default because its usually |
39 | temporary mailboxes stored in memory. */ | 44 | better to retry. */ |
40 | #define MU_LOCKER_RETRY 0x01 | 45 | #define MU_LOCKER_RETRY 0x01 |
41 | /* This requests that we loop retries times, sleeping retry_sleep | 46 | /* This requests that we loop retries times, sleeping retry_sleep |
42 | seconds in between trying to obtain the lock before failing with | 47 | seconds in between trying to obtain the lock before failing with |
... | @@ -51,6 +56,13 @@ extern "C" { | ... | @@ -51,6 +56,13 @@ extern "C" { |
51 | an external dotlocker, non-setgid programs will use a dotlocker, | 56 | an external dotlocker, non-setgid programs will use a dotlocker, |
52 | which locks and exits imediately. This is a protection against | 57 | which locks and exits imediately. This is a protection against |
53 | a server crashing, it's not generally useful. */ | 58 | a server crashing, it's not generally useful. */ |
59 | #define MU_LOCKER_EXTERNAL 0x08 | ||
60 | /* Use an external program to lock the file. This is necessary | ||
61 | for programs having permission to access a file, but do not | ||
62 | have write permission on the directory that contains that file. */ | ||
63 | #define MU_LOCKER_NULL 0x10 | ||
64 | /* Special locker type: means no lock. This is to be used with | ||
65 | temporary mailboxes stored in memory. */ | ||
54 | 66 | ||
55 | #define MU_LOCKER_DEFAULT (MU_LOCKER_RETRY) | 67 | #define MU_LOCKER_DEFAULT (MU_LOCKER_RETRY) |
56 | 68 | ||
... | @@ -63,11 +75,13 @@ extern int locker_set_flags __P ((locker_t, int)); | ... | @@ -63,11 +75,13 @@ extern int locker_set_flags __P ((locker_t, int)); |
63 | extern int locker_set_expire_time __P ((locker_t, int)); | 75 | extern int locker_set_expire_time __P ((locker_t, int)); |
64 | extern int locker_set_retries __P ((locker_t, int)); | 76 | extern int locker_set_retries __P ((locker_t, int)); |
65 | extern int locker_set_retry_sleep __P ((locker_t, int)); | 77 | extern int locker_set_retry_sleep __P ((locker_t, int)); |
78 | extern int locker_set_external __P ((locker_t, const char* program)); | ||
66 | 79 | ||
67 | extern int locker_get_flags __P ((locker_t, int*)); | 80 | extern int locker_get_flags __P ((locker_t, int*)); |
68 | extern int locker_get_expire_time __P ((locker_t, int*)); | 81 | extern int locker_get_expire_time __P ((locker_t, int*)); |
69 | extern int locker_get_retries __P ((locker_t, int*)); | 82 | extern int locker_get_retries __P ((locker_t, int*)); |
70 | extern int locker_get_retry_sleep __P ((locker_t, int*)); | 83 | extern int locker_get_retry_sleep __P ((locker_t, int*)); |
84 | extern int locker_get_external __P ((locker_t, char**)); | ||
71 | 85 | ||
72 | extern int locker_lock __P ((locker_t)); | 86 | extern int locker_lock __P ((locker_t)); |
73 | extern int locker_touchlock __P ((locker_t)); | 87 | extern int locker_touchlock __P ((locker_t)); | ... | ... |
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment