masqmail
changeset 332:63efd381e27b
refactoring, partly also related to set_euidgid()
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Sat, 27 Aug 2011 16:21:17 +0200 |
parents | e507c854a63e |
children | 0bd27f603910 |
files | src/listen.c src/local.c |
diffstat | 2 files changed, 98 insertions(+), 109 deletions(-) [+] |
line diff
1.1 --- a/src/listen.c Sat Aug 27 16:19:07 2011 +0200 1.2 +++ b/src/listen.c Sat Aug 27 16:21:17 2011 +0200 1.3 @@ -131,14 +131,7 @@ 1.4 1.5 /* now that we have our socket(s), we can give up root privileges */ 1.6 if (!conf.run_as_user) { 1.7 - if (setegid(conf.mail_gid) != 0) { 1.8 - logwrite(LOG_ALERT, "could not change gid to %d: %s\n", conf.mail_gid, strerror(errno)); 1.9 - exit(1); 1.10 - } 1.11 - if (seteuid(conf.mail_uid) != 0) { 1.12 - logwrite(LOG_ALERT, "could not change uid to %d: %s\n", conf.mail_uid, strerror(errno)); 1.13 - exit(1); 1.14 - } 1.15 + set_euidgid(conf.mail_uid, conf.mail_gid, NULL, NULL); 1.16 } 1.17 1.18 /* sel_ret = 0; */
2.1 --- a/src/local.c Sat Aug 27 16:19:07 2011 +0200 2.2 +++ b/src/local.c Sat Aug 27 16:21:17 2011 +0200 2.3 @@ -54,94 +54,93 @@ 2.4 { 2.5 struct passwd *pw; 2.6 gboolean ok = FALSE; 2.7 + uid_t saved_uid = geteuid(); 2.8 + gid_t saved_gid = getegid(); 2.9 + gboolean uid_ok = TRUE, gid_ok = TRUE; 2.10 + gchar *filename; 2.11 + FILE *out; 2.12 2.13 /* headers may be special for a local delivery */ 2.14 - if (hdr_list == NULL) 2.15 + if (!hdr_list) 2.16 hdr_list = msg->hdr_list; 2.17 2.18 - if ((pw = getpwnam(user))) { 2.19 - uid_t saved_uid = geteuid(); 2.20 - gid_t saved_gid = getegid(); 2.21 - gboolean uid_ok = TRUE, gid_ok = TRUE; 2.22 - 2.23 - if (!conf.run_as_user) { 2.24 - uid_ok = (seteuid(0) == 0); 2.25 - if (uid_ok) { 2.26 - gid_ok = (setegid(conf.mail_gid) == 0); 2.27 - uid_ok = (seteuid(pw->pw_uid) == 0); 2.28 - } 2.29 - } 2.30 - 2.31 - DEBUG(5) debugf("running as euid %d, egid %d\n", geteuid(), getegid()); 2.32 - 2.33 - if (uid_ok && gid_ok) { 2.34 - gchar *filename; 2.35 - FILE *out; 2.36 - 2.37 - filename = g_strdup_printf("%s/%s", conf.mail_dir, user); 2.38 - if ((out = fopen(filename, "a"))) { 2.39 -#ifdef USE_LIBLOCKFILE 2.40 - gint err; 2.41 - /* lock file using liblockfile */ 2.42 - err = maillock(user, 3); 2.43 - if (err == 0) { 2.44 -#else 2.45 - /* lock file: */ 2.46 - struct flock lock; 2.47 - lock.l_type = F_WRLCK; 2.48 - lock.l_whence = SEEK_END; 2.49 - lock.l_start = lock.l_len = 0; 2.50 - if (fcntl(fileno(out), F_SETLK, &lock) != -1) { 2.51 -#endif 2.52 - fchmod(fileno(out), 0600); 2.53 - message_stream(out, msg, hdr_list, MSGSTR_FROMLINE | MSGSTR_FROMHACK); 2.54 - ok = TRUE; 2.55 - 2.56 - /* close when still user */ 2.57 - fclose(out); 2.58 -#ifdef USE_LIBLOCKFILE 2.59 - mailunlock(); 2.60 -#endif 2.61 - } else { 2.62 - fclose(out); 2.63 -#ifdef USE_LIBLOCKFILE 2.64 - DEBUG(3) debugf("could not lock file %s: error %d\n", filename, err); 2.65 - } /* XEmacs indenting convenience... */ 2.66 -#else 2.67 - DEBUG(3) debugf("could not lock file %s: %s\n", filename, strerror(errno)); 2.68 - } 2.69 -#endif 2.70 - } else { 2.71 - logwrite(LOG_ALERT, "could not open file %s: %s\n", filename, strerror(errno)); 2.72 - } 2.73 - g_free(filename); 2.74 - 2.75 - if (!conf.run_as_user) { 2.76 - uid_ok = (seteuid(0) == 0); 2.77 - if (uid_ok) { 2.78 - gid_ok = (setegid(saved_gid) == 0); 2.79 - uid_ok = (seteuid(saved_uid) == 0); 2.80 - } 2.81 - } 2.82 - 2.83 - if (!uid_ok || !gid_ok) { 2.84 - /* FIXME: if this fails we HAVE to exit, because we shall not run 2.85 - with some users id. But we do not return, and so this message 2.86 - will not be finished, so the user will get the message again 2.87 - next time a delivery is attempted... */ 2.88 - logwrite(LOG_ALERT, "could not set back uid or gid after local delivery: %s\n", strerror(errno)); 2.89 - logwrite(LOG_ALERT, "uid=%d, gid=%d, euid=%d, egid=%d, want = %d, %d\n", 2.90 - getuid(), getgid(), geteuid(), getegid(), saved_uid, saved_gid); 2.91 - exit(1); 2.92 - } 2.93 - } else { 2.94 - logwrite(LOG_ALERT, "could not set uid or gid for local delivery, uid = %d: %s\n", pw->pw_uid, strerror(errno)); 2.95 - } 2.96 - } else { 2.97 + if (!(pw = getpwnam(user))) { 2.98 logwrite(LOG_ALERT, "could not find password entry for user %s\n", user); 2.99 errno = ENOENT; /* getpwnam does not set errno correctly */ 2.100 + return FALSE; 2.101 } 2.102 2.103 + if (!conf.run_as_user) { 2.104 + uid_ok = (seteuid(0) == 0); 2.105 + if (uid_ok) { 2.106 + gid_ok = (setegid(conf.mail_gid) == 0); 2.107 + uid_ok = (seteuid(pw->pw_uid) == 0); 2.108 + } 2.109 + if (!uid_ok || !gid_ok) { 2.110 + logwrite(LOG_ALERT, "could not set uid or gid for local delivery, uid = %d: %s\n", pw->pw_uid, strerror(errno)); 2.111 + return FALSE; 2.112 + } 2.113 + } 2.114 + 2.115 + DEBUG(5) debugf("running as euid %d, egid %d\n", geteuid(), getegid()); 2.116 + 2.117 + filename = g_strdup_printf("%s/%s", conf.mail_dir, user); 2.118 + if (!(out = fopen(filename, "a"))) { 2.119 + logwrite(LOG_ALERT, "could not open file %s: %s\n", filename, strerror(errno)); 2.120 + } else { 2.121 +#ifdef USE_LIBLOCKFILE 2.122 + gint err; 2.123 + /* lock file using liblockfile */ 2.124 + err = maillock(user, 3); 2.125 + if (err == 0) { 2.126 +#else 2.127 + /* lock file: */ 2.128 + struct flock lock; 2.129 + lock.l_type = F_WRLCK; 2.130 + lock.l_whence = SEEK_END; 2.131 + lock.l_start = lock.l_len = 0; 2.132 + if (fcntl(fileno(out), F_SETLK, &lock) != -1) { 2.133 +#endif 2.134 + fchmod(fileno(out), 0600); 2.135 + message_stream(out, msg, hdr_list, MSGSTR_FROMLINE | MSGSTR_FROMHACK); 2.136 + ok = TRUE; 2.137 + 2.138 + /* close when still user */ 2.139 + fclose(out); 2.140 +#ifdef USE_LIBLOCKFILE 2.141 + mailunlock(); 2.142 +#endif 2.143 + } else { 2.144 + fclose(out); 2.145 +#ifdef USE_LIBLOCKFILE 2.146 + DEBUG(3) debugf("could not lock file %s: error %d\n", filename, err); 2.147 + } /* XEmacs indenting convenience... */ 2.148 +#else 2.149 + DEBUG(3) debugf("could not lock file %s: %s\n", filename, strerror(errno)); 2.150 + } 2.151 +#endif 2.152 + } 2.153 + g_free(filename); 2.154 + 2.155 + if (!conf.run_as_user) { 2.156 + uid_ok = (seteuid(0) == 0); 2.157 + if (uid_ok) { 2.158 + gid_ok = (setegid(saved_gid) == 0); 2.159 + uid_ok = (seteuid(saved_uid) == 0); 2.160 + } 2.161 + } 2.162 + 2.163 + if (!uid_ok || !gid_ok) { 2.164 + /* FIXME: if this fails we HAVE to exit, because we shall not run 2.165 + with some users id. But we do not return, and so this message 2.166 + will not be finished, so the user will get the message again 2.167 + next time a delivery is attempted... */ 2.168 + logwrite(LOG_ALERT, "could not set back uid or gid after local delivery: %s\n", strerror(errno)); 2.169 + logwrite(LOG_ALERT, "uid=%d, gid=%d, euid=%d, egid=%d, want = %d, %d\n", 2.170 + getuid(), getgid(), geteuid(), getegid(), saved_uid, saved_gid); 2.171 + logwrite(LOG_ALERT, "In case of trouble, see local.c:append_file() for details.\n", strerror(errno)); 2.172 + exit(1); 2.173 + } 2.174 return ok; 2.175 } 2.176 2.177 @@ -157,6 +156,7 @@ 2.178 pid_t pid; 2.179 void (*old_signal) (int); 2.180 int status; 2.181 + address *ancestor = addr_find_ancestor(rcpt); 2.182 2.183 /* set uid and gid to the mail ids */ 2.184 if (!conf.run_as_user) { 2.185 @@ -164,33 +164,30 @@ 2.186 } 2.187 2.188 /* set environment */ 2.189 - { 2.190 - gint i = 0; 2.191 - address *ancestor = addr_find_ancestor(rcpt); 2.192 + n = 0; 2.193 + envp[n++] = g_strdup_printf("SENDER=%s@%s", msg->return_path->local_part, msg->return_path->domain); 2.194 + envp[n++] = g_strdup_printf("SENDER_DOMAIN=%s", msg->return_path->domain); 2.195 + envp[n++] = g_strdup_printf("SENDER_LOCAL=%s", msg->return_path->local_part); 2.196 + envp[n++] = g_strdup_printf("RECEIVED_HOST=%s", msg->received_host ? msg->received_host : ""); 2.197 2.198 - envp[i++] = g_strdup_printf("SENDER=%s@%s", msg->return_path->local_part, msg->return_path->domain); 2.199 - envp[i++] = g_strdup_printf("SENDER_DOMAIN=%s", msg->return_path->domain); 2.200 - envp[i++] = g_strdup_printf("SENDER_LOCAL=%s", msg->return_path->local_part); 2.201 - envp[i++] = g_strdup_printf("RECEIVED_HOST=%s", msg->received_host ? msg->received_host : ""); 2.202 + envp[n++] = g_strdup_printf("RETURN_PATH=%s@%s", msg->return_path->local_part, msg->return_path->domain); 2.203 + envp[n++] = g_strdup_printf("DOMAIN=%s", ancestor->domain); 2.204 2.205 - envp[i++] = g_strdup_printf("RETURN_PATH=%s@%s", msg->return_path->local_part, msg->return_path->domain); 2.206 - envp[i++] = g_strdup_printf("DOMAIN=%s", ancestor->domain); 2.207 + envp[n++] = g_strdup_printf("LOCAL_PART=%s", ancestor->local_part); 2.208 + envp[n++] = g_strdup_printf("USER=%s", ancestor->local_part); 2.209 + envp[n++] = g_strdup_printf("LOGNAME=%s", ancestor->local_part); 2.210 2.211 - envp[i++] = g_strdup_printf("LOCAL_PART=%s", ancestor->local_part); 2.212 - envp[i++] = g_strdup_printf("USER=%s", ancestor->local_part); 2.213 - envp[i++] = g_strdup_printf("LOGNAME=%s", ancestor->local_part); 2.214 + envp[n++] = g_strdup_printf("MESSAGE_ID=%s", msg->uid); 2.215 + envp[n++] = g_strdup_printf("QUALIFY_DOMAIN=%s", conf.host_name); 2.216 2.217 - envp[i++] = g_strdup_printf("MESSAGE_ID=%s", msg->uid); 2.218 - envp[i++] = g_strdup_printf("QUALIFY_DOMAIN=%s", conf.host_name); 2.219 - 2.220 - envp[i] = NULL; 2.221 - n = i; 2.222 - } 2.223 + envp[n] = NULL; 2.224 2.225 old_signal = signal(SIGCHLD, SIG_DFL); 2.226 2.227 out = peidopen(cmd, "w", envp, &pid, conf.mail_uid, conf.mail_gid); 2.228 - if (out != NULL) { 2.229 + if (!out) { 2.230 + logwrite(LOG_ALERT, "could not open pipe '%s': %s\n", cmd, strerror(errno)); 2.231 + } else { 2.232 message_stream(out, msg, hdr_list, flags); 2.233 2.234 fclose(out); 2.235 @@ -206,8 +203,7 @@ 2.236 } else 2.237 ok = TRUE; 2.238 2.239 - } else 2.240 - logwrite(LOG_ALERT, "could not open pipe '%s': %s\n", cmd, strerror(errno)); 2.241 + } 2.242 2.243 signal(SIGCHLD, old_signal); 2.244