Update sync_site.yml
[m6w6/m6w6.github.io] / _posts / 2011-03-14-courier-imap-authdaemond-and-vpopmails-vchkpw.md
1 ---
2 title: courier imap, authdaemond and vpopmails vchkpw
3 author: m6w6
4 tags:
5 - WTF
6 - SYS
7 ---
8
9 A few years ago, it was possible to have courier-imap update the open-smtp
10 relay file with it's authvchkpw module. This feature and thus imap-before-smtp
11 disappeared with the introduction of courier-authdaemond because the vchkpw
12 code of authdaemond does not have a chance to see the TCPREMOTEIP environment
13 variable.
14
15 I more or less lived with that, until a friend of mine got a new iphone...
16 well yeah, one of those i-geeks, and that gadget apparently only supports
17 imap, no pop.
18
19 To re-enable imap-before-smtp I wrote a little setuid wrapper, calling
20 vpopmails open_smtp_relay(). This wrapper has to replace the imapd command in
21 your courier-imap startup script and will exec imapd, after opening the smtp
22 relay, wile imap-login is still in place to authenticate via authdaemond's
23 vchkpw module.
24
25 ```c
26 #include <unistd.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <vpopmail_config.h>
30 #include <vauth.h>
31 #include <vpopmail.h>
32
33 #ifndef IMAPD
34 # define IMAPD "/usr/bin/imapd"
35 #endif
36
37 extern char **environ;
38
39 int main(int argc, const char *argv[]) {
40 if (argc != 2) {
41 printf("1 NO argc != 2n");
42 return -1;
43 }
44
45 open_smtp_relay();
46 /* no need to chown vpopmail.vchkpw the open-smtp file
47 * because vchkpw used by qmail-pop3d is setuid root */
48
49 sleep(1);
50
51 if (setgid(VPOPMAILGID) || setuid(VPOPMAILUID)) {
52 printf("1 NO setuid/gid, getuid=%dn", getuid());
53 return -2;
54 }
55
56 execl(IMAPD, IMAPD, argv[1], NULL);
57
58 printf("1 NO exec %s failedn", IMAPD);
59 return -3;
60 }
61 ```
62
63 So while this worked to my satisfaction, I noticed that the tcp.smtp.cdb not
64 always contained the IPs of the open-smtp file:
65 ```sh
66 $ for ip in $(sed -re 's/:.*//' < open-smtp); do
67 cdbget $ip < tcp.smtp.cdb > /dev/null
68 || echo "$ip is missing";
69 done
70 ```
71
72 I also found out that, while the [vpopmail FAQ](http://www.inter7.com/vpopmail/FAQ.txt) is claiming
73 that clearopensmtp is requesting locks on the open-smtp(.lock) file, the source does not read like
74 it would.
75
76 I opened a [bug report](https://sourceforge.net/tracker/?func=detail&aid=3205655&group_id=85937&atid=577798)
77 for that issue, but as you might have already guessed, I'm running all of this
78 on an archaic debian box, where no upgrades are planned. So I came up with
79 another home-brewed solution:
80
81 ```c
82 #include <unistd.h>
83 #include <stdio.h>
84 #include <sys/types.h>
85 #include <vpopmail_config.h>
86 #include <vauth.h>
87 #include <vpopmail.h>
88 #include <fcntl.h>
89
90 extern int get_write_lock(FILE*);
91 extern int lock_reg(int,int,int,off_t,int,off_t);
92 #define unlock(F) lock_reg(fileno(F), F_SETLK, F_UNLCK, 0, SEEK_SET, 0)
93
94 int main(int argc, const char *argv[]) {
95 FILE *fs_temp, *fs_smtp, *fs_lock = fopen(OPEN_SMTP_LOK_FILE, "w+");
96 time_t clear = RELAY_CLEAR_MINUTES * 60, now = time(NULL);
97 int cc = 0, rc = 0;
98
99 if (!fs_lock) {
100 return -1;
101 }
102 if (get_write_lock(fs_lock)) {
103 unlock(fs_lock);
104 fclose(fs_lock);
105 return -2;
106 }
107
108 if (!(fs_temp = fopen(OPEN_SMTP_TMP_FILE ".clear", "w"))) {
109 rc = -3;
110 } else if (!(fs_smtp = fopen(OPEN_SMTP_CUR_FILE, "r+"))) {
111 fclose(fs_temp);
112 rc = -4;
113 } else {
114 while (!rc && !feof(fs_smtp)) {
115 unsigned stime;
116 char sdata[256];
117
118 switch (fscanf(fs_smtp, "%255st%un", sdata, &stime)) {
119 case 2:
120 if ((clear + stime) >= now) {
121 fprintf(fs_temp, "%st%un", sdata, stime);
122 } else {
123 ++cc;
124 }
125 break;
126
127 default:
128 rc = -5;
129 case EOF:
130 break;
131 }
132 }
133 fclose(fs_smtp);
134 fclose(fs_temp);
135 }
136
137 if (!rc) {
138 if (cc) {
139 if (rename(OPEN_SMTP_TMP_FILE ".clear", OPEN_SMTP_CUR_FILE)) {
140 rc = -6;
141 } else if(update_rules()) {
142 rc = -7;
143 }
144 } else {
145 unlink(OPEN_SMTP_TMP_FILE ".clear");
146 }
147 }
148
149 unlock(fs_lock);
150 fclose(fs_lock);
151 return rc;
152 }
153 ```
154
155 It's not the prettiest piece of code, but it helps.
156 Well, maybe someone else running last-millenium software finds this useful
157