]>
Commit | Line | Data |
---|---|---|
6b3d3fd3 | 1 | diff -urP exim-4.20.orig/doc/README.saslauthd.txt exim-4.20/doc/README.saslauthd.txt |
2 | --- exim-4.20.orig/doc/README.saslauthd.txt 1970-01-01 01:00:00.000000000 +0100 | |
3 | +++ exim-4.20/doc/README.saslauthd.txt 2003-07-09 02:46:14.000000000 +0200 | |
4 | @@ -0,0 +1,31 @@ | |
5 | +This is sample configuration for enabling authorization mechanism in | |
6 | +Exim-4.20 using saslauthd from pacakge cyrus-sasl-saslauthd-2.x (note: | |
7 | +not from cyrus-sasl-saslauthd-1.5.27, that provides *pwcheck* daemon): | |
8 | + | |
9 | +-8<-cut-here--------------------------------------------------------- | |
10 | + | |
11 | +begin authenticators | |
12 | + | |
13 | +plain: | |
14 | + driver = plaintext | |
15 | + public_name = PLAIN | |
16 | + server_condition = ${if saslauthd{$1:$3:smtp}{1}{0}} | |
17 | + server_set_id = $2 | |
18 | + | |
19 | +login: | |
20 | + driver = plaintext | |
21 | + public_name = LOGIN | |
22 | + server_prompts = "Username:: : Password::" | |
23 | + server_condition = ${if saslauthd{$1:$2:smtp}{1}{0}} | |
24 | + server_set_id = $1 | |
25 | + | |
26 | +-8<-cut-here--------------------------------------------------------- | |
27 | + | |
28 | +Orginal patch has been developed by Alexander Sabourenkov <lists at lxnt.info> | |
29 | +and can be find on <http://lxnt.info/stuff/saslauthd.diff>. The syntax of | |
30 | +of saslauthd condition is simmilar to pwcheck: | |
31 | + | |
32 | +${if saslauthd{{<username>}{<password>}[{<servicename>}[{<realm>}]]}{1}{0}} | |
33 | + | |
34 | +Baseciq <baseciq@pld-linux.org> | |
35 | + | |
36 | diff -urP exim-4.20.orig/doc/README.saslauthd.txt~ exim-4.20/doc/README.saslauthd.txt~ | |
37 | --- exim-4.20.orig/doc/README.saslauthd.txt~ 1970-01-01 01:00:00.000000000 +0100 | |
38 | +++ exim-4.20/doc/README.saslauthd.txt~ 2003-07-09 02:34:46.000000000 +0200 | |
39 | @@ -0,0 +1,31 @@ | |
40 | +This is sample configuration for enabling authorization mechanism in | |
41 | +Exim-4.20 using saslauthd (not pwcheck!) from pacakge | |
42 | +cyrus-sasl-saslauthd-2.x: | |
43 | + | |
44 | +-8<-cut-here--------------------------------------------------------- | |
45 | + | |
46 | +begin authenticators | |
47 | + | |
48 | +plain: | |
49 | + driver = plaintext | |
50 | + public_name = PLAIN | |
51 | + server_condition = ${if saslauthd{$1:$3:smtp}{1}{0}} | |
52 | + server_set_id = $2 | |
53 | + | |
54 | +login: | |
55 | + driver = plaintext | |
56 | + public_name = LOGIN | |
57 | + server_prompts = "Username:: : Password::" | |
58 | + server_condition = ${if saslauthd{$1:$2:smtp}{1}{0}} | |
59 | + server_set_id = $1 | |
60 | + | |
61 | +-8<-cut-here--------------------------------------------------------- | |
62 | + | |
63 | +Orginal patch has been developed by Alexander Sabourenkov <lists at lxnt.info> | |
64 | +and can be find on <http://lxnt.info/stuff/saslauthd.diff>. The syntax of | |
65 | +of saslauthd condition is simmilar to pwcheck: | |
66 | + | |
67 | +${if saslauthd{{<username>}{<password>}[{<servicename>}[{<realm>}]]}{1}{0}} | |
68 | + | |
69 | +Baseciq <baseciq@pld-linux.org> | |
70 | + | |
71 | diff -urP exim-4.20.orig/src/auths/call_pwcheck.c exim-4.20/src/auths/call_pwcheck.c | |
72 | --- exim-4.20.orig/src/auths/call_pwcheck.c 2003-07-09 02:04:25.000000000 +0200 | |
73 | +++ exim-4.20/src/auths/call_pwcheck.c 2003-07-09 02:04:37.000000000 +0200 | |
74 | @@ -13,7 +13,7 @@ | |
75 | * External entry point * | |
76 | *************************************************/ | |
77 | ||
78 | -/* This function calls the Cyrus-SASL authentication daemon, passing over a | |
79 | +/* This function calls a Cyrus-SASL authentication daemon, pwcheck, passing over a | |
80 | colon-separated user name and password. As this is called from the string | |
81 | expander, the string will always be in dynamic store and can be overwritten. | |
82 | ||
83 | @@ -50,7 +50,7 @@ | |
84 | DEBUG(D_auth) debug_printf("pwcheck: success (%s)\n", reply); | |
85 | return OK; | |
86 | ||
87 | - case PWCHECK_BAD: | |
88 | + case PWCHECK_NO: | |
89 | DEBUG(D_auth) debug_printf("pwcheck: access denied (%s)\n", reply); | |
90 | return FAIL; | |
91 | ||
92 | @@ -61,4 +61,75 @@ | |
93 | } | |
94 | } | |
95 | ||
96 | +/************************************************* | |
97 | +* External entry point * | |
98 | +*************************************************/ | |
99 | + | |
100 | +/* This function calls a Cyrus-SASL authentication daemon, saslauthd, | |
101 | +passing over a colon-separated user name and password. As this is called | |
102 | +from the string expander, the string will always be in dynamic store and | |
103 | +can be overwritten. | |
104 | + | |
105 | +Arguments: | |
106 | + s a colon-separated username:password[:servicename[:realm]] string | |
107 | + errptr where to point an error message | |
108 | + | |
109 | +Returns: OK if authentication succeeded | |
110 | + FAIL if authentication failed | |
111 | + ERROR some other error condition | |
112 | +*/ | |
113 | + | |
114 | + | |
115 | +int | |
116 | +auth_call_saslauthd(uschar *s, uschar **errptr) | |
117 | +{ | |
118 | +uschar *reply = NULL; | |
119 | +uschar *pw = Ustrchr(s, ':'); | |
120 | +uschar *service, *realm; | |
121 | + | |
122 | +if (pw == NULL) | |
123 | + { | |
124 | + *errptr = US"saslauthd: malformed input - missing colon"; | |
125 | + return ERROR; | |
126 | + } | |
127 | + | |
128 | +*pw++ = 0; /* Separate user and password */ | |
129 | +service = Ustrchr(pw, ':'); | |
130 | +if (service != NULL ) | |
131 | + { | |
132 | + *service++ = 0; | |
133 | + realm = Ustrchr(service, ':'); | |
134 | + if ( realm != NULL ) | |
135 | + *realm++ = 0; | |
136 | + else | |
137 | + realm = ""; | |
138 | + } | |
139 | +else | |
140 | + { | |
141 | + service = ""; | |
142 | + realm = ""; | |
143 | + } | |
144 | + | |
145 | + | |
146 | +DEBUG(D_auth) | |
147 | + debug_printf("Running saslauthd authentication for user \"%s\"\n", s); | |
148 | + | |
149 | +switch (saslauthd_verify_password(CS s, CS pw, CS service, CS realm, (const char **)(&reply))) | |
150 | + { | |
151 | + case PWCHECK_OK: | |
152 | + DEBUG(D_auth) debug_printf("saslauthd: success (%s)\n", reply); | |
153 | + return OK; | |
154 | + | |
155 | + case PWCHECK_NO: | |
156 | + DEBUG(D_auth) debug_printf("saslauthd: access denied (%s)\n", reply); | |
157 | + return FAIL; | |
158 | + | |
159 | + default: | |
160 | + DEBUG(D_auth) debug_printf("saslauthd: query failed (%s)\n", reply); | |
161 | + *errptr = reply; | |
162 | + return ERROR; | |
163 | + } | |
164 | +} | |
165 | + | |
166 | + | |
167 | /* End of call_pwcheck.c */ | |
168 | diff -urP exim-4.20.orig/src/auths/pwcheck.c exim-4.20/src/auths/pwcheck.c | |
169 | --- exim-4.20.orig/src/auths/pwcheck.c 2003-07-09 02:04:25.000000000 +0200 | |
170 | +++ exim-4.20/src/auths/pwcheck.c 2003-07-09 02:04:37.000000000 +0200 | |
171 | @@ -45,7 +45,7 @@ | |
172 | ||
173 | /* | |
174 | * Taken from Cyrus-SASL library and adapted by Alexander S. Sabourenkov | |
175 | - * Oct 2001 - Apr 2002. Slightly modified by Philip Hazel. | |
176 | + * Oct 2001 - Apr 2003. Slightly modified by Philip Hazel. | |
177 | * | |
178 | * screwdriver@lxnt.info | |
179 | * | |
180 | @@ -55,6 +55,17 @@ | |
181 | #include "../exim.h" | |
182 | #include "pwcheck.h" | |
183 | ||
184 | +#if defined(CYRUS_PWCHECK_SOCKET) || defined(CYRUS_SASLAUTHD_SOCKET) | |
185 | + | |
186 | +#include <sys/uio.h> | |
187 | + | |
188 | +static int retry_read(int, void *, unsigned ); | |
189 | +static int retry_writev(int, struct iovec *, int ); | |
190 | +static int read_string(int, uschar **); | |
191 | +static int write_string(int, const uschar *, int); | |
192 | + | |
193 | +#endif | |
194 | + | |
195 | /* A dummy function that always fails if pwcheck support is not | |
196 | wanted. */ | |
197 | ||
198 | @@ -73,65 +84,6 @@ | |
199 | /* This is the real function */ | |
200 | ||
201 | #else | |
202 | -#include <sys/uio.h> | |
203 | - | |
204 | - | |
205 | - /* taken from cyrus-sasl file checkpw.c */ | |
206 | - /* | |
207 | - * Keep calling the writev() system call with 'fd', 'iov', and 'iovcnt' | |
208 | - * until all the data is written out or an error occurs. | |
209 | - */ | |
210 | - static int retry_writev(int fd, struct iovec *iov, int iovcnt) | |
211 | - { | |
212 | - int n; | |
213 | - int i; | |
214 | - int written = 0; | |
215 | - static int iov_max = | |
216 | - #ifdef MAXIOV | |
217 | - MAXIOV | |
218 | - #else | |
219 | - #ifdef IOV_MAX | |
220 | - IOV_MAX | |
221 | - #else | |
222 | - 8192 | |
223 | - #endif | |
224 | - #endif | |
225 | - ; | |
226 | - | |
227 | - for (;;) { | |
228 | - while (iovcnt && iov[0].iov_len == 0) { | |
229 | - iov++; | |
230 | - iovcnt--; | |
231 | - } | |
232 | - | |
233 | - if (!iovcnt) return written; | |
234 | - | |
235 | - n = writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt); | |
236 | - if (n == -1) { | |
237 | - if (errno == EINVAL && iov_max > 10) { | |
238 | - iov_max /= 2; | |
239 | - continue; | |
240 | - } | |
241 | - if (errno == EINTR) continue; | |
242 | - return -1; | |
243 | - } | |
244 | - | |
245 | - written += n; | |
246 | - | |
247 | - for (i = 0; i < iovcnt; i++) { | |
248 | - if (iov[i].iov_len > n) { | |
249 | - iov[i].iov_base = (char *)iov[i].iov_base + n; | |
250 | - iov[i].iov_len -= n; | |
251 | - break; | |
252 | - } | |
253 | - n -= iov[i].iov_len; | |
254 | - iov[i].iov_len = 0; | |
255 | - } | |
256 | - | |
257 | - if (i == iovcnt) return written; | |
258 | - } | |
259 | - } | |
260 | - | |
261 | ||
262 | /* taken from cyrus-sasl file checkpw.c */ | |
263 | /* pwcheck daemon-authenticated login */ | |
264 | @@ -139,18 +91,15 @@ | |
265 | const char *passwd, | |
266 | const char **reply) | |
267 | { | |
268 | - int s; | |
269 | + int s, start, r, n; | |
270 | struct sockaddr_un srvaddr; | |
271 | - int r; | |
272 | - struct iovec iov[10]; | |
273 | + struct iovec iov[2]; | |
274 | static char response[1024]; | |
275 | - int start, n; | |
276 | - /* char pwpath[1024]; is not used - PH */ | |
277 | ||
278 | if (reply) { *reply = NULL; } | |
279 | ||
280 | s = socket(AF_UNIX, SOCK_STREAM, 0); | |
281 | - if (s == -1) return errno; | |
282 | + if (s == -1) { return PWCHECK_FAIL; } | |
283 | ||
284 | memset((char *)&srvaddr, 0, sizeof(srvaddr)); | |
285 | srvaddr.sun_family = AF_UNIX; | |
286 | @@ -185,9 +134,307 @@ | |
287 | ||
288 | response[start] = '\0'; | |
289 | if (reply) { *reply = response; } | |
290 | - return PWCHECK_BAD; | |
291 | + return PWCHECK_NO; | |
292 | } | |
293 | ||
294 | #endif | |
295 | ||
296 | + | |
297 | + /* A dummy function that always fails if saslauthd support is not | |
298 | +wanted. */ | |
299 | + | |
300 | +#ifndef CYRUS_SASLAUTHD_SOCKET | |
301 | +int saslauthd_verify_password(const char *userid, | |
302 | + const char *passwd, | |
303 | + const char *service, | |
304 | + const char *realm, | |
305 | + const char **reply) | |
306 | +{ | |
307 | +userid = userid; /* Keep picky compilers happy */ | |
308 | +passwd = passwd; | |
309 | +service = service; | |
310 | +realm = realm; | |
311 | +*reply = "saslauthd support is not included in this Exim binary"; | |
312 | +return PWCHECK_FAIL; | |
313 | +} | |
314 | + | |
315 | + | |
316 | +/* This is the real function */ | |
317 | + | |
318 | +#else | |
319 | + /* written from scratch */ | |
320 | + /* saslauthd daemon-authenticated login */ | |
321 | + | |
322 | +int saslauthd_verify_password(const char *userid, | |
323 | + const char *password, | |
324 | + const char *service, | |
325 | + const char *realm, | |
326 | + const char **reply) | |
327 | +{ | |
328 | + uschar *daemon_reply; | |
329 | + int s, r; | |
330 | + struct sockaddr_un srvaddr; | |
331 | + | |
332 | + DEBUG(D_auth) | |
333 | + debug_printf("saslauthd userid='%s' password='%s' servicename='%s'" | |
334 | + " realm='%s'\n", userid, password, service, realm ); | |
335 | + | |
336 | + if (reply) | |
337 | + *reply = NULL; | |
338 | + | |
339 | + s = socket(AF_UNIX, SOCK_STREAM, 0); | |
340 | + if (s == -1) { | |
341 | + if (reply) | |
342 | + *reply = strerror(errno); | |
343 | + return PWCHECK_FAIL; | |
344 | + } | |
345 | + | |
346 | + memset((char *)&srvaddr, 0, sizeof(srvaddr)); | |
347 | + srvaddr.sun_family = AF_UNIX; | |
348 | + strncpy(srvaddr.sun_path, CYRUS_SASLAUTHD_SOCKET, | |
349 | + sizeof(srvaddr.sun_path)); | |
350 | + r = connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr)); | |
351 | + if (r == -1) { | |
352 | + DEBUG(D_auth) | |
353 | + debug_printf("Cannot connect to saslauthd daemon (at '%s'): %s\n", | |
354 | + CYRUS_SASLAUTHD_SOCKET, strerror(errno)); | |
355 | + if (reply) | |
356 | + *reply = string_sprintf("cannot connect to saslauthd daemon at " | |
357 | + "%s: %s", strerror(errno)); | |
358 | + return PWCHECK_FAIL; | |
359 | + } | |
360 | + | |
361 | + if ( write_string(s, userid, strlen(userid)) < 0) { | |
362 | + DEBUG(D_auth) | |
363 | + debug_printf("Failed to send userid to saslauthd daemon \n"); | |
364 | + close(s); | |
365 | + return PWCHECK_FAIL; | |
366 | + } | |
367 | + | |
368 | + if ( write_string(s, password, strlen(password)) < 0) { | |
369 | + DEBUG(D_auth) | |
370 | + debug_printf("Failed to send password to saslauthd daemon \n"); | |
371 | + close(s); | |
372 | + return PWCHECK_FAIL; | |
373 | + } | |
374 | + | |
375 | + memset(password, 0, strlen(password)); | |
376 | + | |
377 | + if ( write_string(s, service, strlen(service)) < 0) { | |
378 | + DEBUG(D_auth) | |
379 | + debug_printf("Failed to send service name to saslauthd daemon \n"); | |
380 | + close(s); | |
381 | + return PWCHECK_FAIL; | |
382 | + } | |
383 | + | |
384 | + if ( write_string(s, realm, strlen(realm)) < 0) { | |
385 | + DEBUG(D_auth) | |
386 | + debug_printf("Failed to send realm to saslauthd daemon \n"); | |
387 | + close(s); | |
388 | + return PWCHECK_FAIL; | |
389 | + } | |
390 | + | |
391 | + if ( read_string(s, &daemon_reply ) < 2) { | |
392 | + DEBUG(D_auth) | |
393 | + debug_printf("Corrupted answer '%s' received. \n", daemon_reply); | |
394 | + close(s); | |
395 | + return PWCHECK_FAIL; | |
396 | + } | |
397 | + | |
398 | + close(s); | |
399 | + | |
400 | + DEBUG(D_auth) | |
401 | + debug_printf("Answer '%s' received. \n", daemon_reply); | |
402 | + | |
403 | + *reply = daemon_reply; | |
404 | + | |
405 | + if ( (daemon_reply[0] == 'O') && (daemon_reply[1] == 'K') ) | |
406 | + return PWCHECK_OK; | |
407 | + | |
408 | + if ( (daemon_reply[0] == 'N') && (daemon_reply[1] == 'O') ) | |
409 | + return PWCHECK_NO; | |
410 | + | |
411 | + return PWCHECK_FAIL; | |
412 | +} | |
413 | + | |
414 | +#endif | |
415 | + | |
416 | + | |
417 | +/* helper functions */ | |
418 | +#if defined(CYRUS_PWCHECK_SOCKET) || defined(CYRUS_SASLAUTHD_SOCKET) | |
419 | + | |
420 | +#define MAX_REQ_LEN 1024 | |
421 | + | |
422 | +/* written from scratch */ | |
423 | + | |
424 | +/* FUNCTION: read_string */ | |
425 | + | |
426 | +/* SYNOPSIS | |
427 | + * read a sasld-style counted string into | |
428 | + * store-allocated buffer, set pointer to the buffer, | |
429 | + * return number of bytes read or -1 on failure. | |
430 | + * END SYNOPSIS */ | |
431 | + | |
432 | +static int read_string(int fd, uschar **retval) { | |
433 | + unsigned short count; | |
434 | + int rc; | |
435 | + | |
436 | + rc = (retry_read(fd, &count, sizeof(count)) < (int) sizeof(count)); | |
437 | + if (!rc) { | |
438 | + count = ntohs(count); | |
439 | + if (count > MAX_REQ_LEN) { | |
440 | + return -1; | |
441 | + } else { | |
442 | + *retval = store_get(count + 1); | |
443 | + rc = (retry_read(fd, *retval, count) < (int) count); | |
444 | + (*retval)[count] = '\0'; | |
445 | + return count; | |
446 | + } | |
447 | + } | |
448 | +} | |
449 | + | |
450 | + | |
451 | +/* FUNCTION: write_string */ | |
452 | + | |
453 | +/* SYNOPSIS | |
454 | + * write a sasld-style counted string into given fd | |
455 | + * written bytes on success, -1 on failure. | |
456 | + * END SYNOPSIS */ | |
457 | + | |
458 | +static int write_string(int fd, const uschar *string, int len) { | |
459 | + unsigned short count; | |
460 | + int rc; | |
461 | + struct iovec iov[2]; | |
462 | + | |
463 | + count = htons(len); | |
464 | + | |
465 | + iov[0].iov_base = (void *) &count; | |
466 | + iov[0].iov_len = sizeof(count); | |
467 | + iov[1].iov_base = (void *) string; | |
468 | + iov[1].iov_len = len; | |
469 | + | |
470 | + rc = retry_writev(fd, iov, 2); | |
471 | + | |
472 | + return rc; | |
473 | +} | |
474 | + | |
475 | + | |
476 | +/* taken from cyrus-sasl file saslauthd/saslauthd-unix.c */ | |
477 | + | |
478 | +/* FUNCTION: retry_read */ | |
479 | + | |
480 | +/* SYNOPSIS | |
481 | + * Keep calling the read() system call with 'fd', 'buf', and 'nbyte' | |
482 | + * until all the data is read in or an error occurs. | |
483 | + * END SYNOPSIS */ | |
484 | +static int retry_read(int fd, void *inbuf, unsigned nbyte) | |
485 | +{ | |
486 | + int n; | |
487 | + int nread = 0; | |
488 | + char *buf = (char *)inbuf; | |
489 | + | |
490 | + if (nbyte == 0) return 0; | |
491 | + | |
492 | + for (;;) { | |
493 | + n = read(fd, buf, nbyte); | |
494 | + if (n == 0) { | |
495 | + /* end of file */ | |
496 | + return -1; | |
497 | + } | |
498 | + if (n == -1) { | |
499 | + if (errno == EINTR) continue; | |
500 | + return -1; | |
501 | + } | |
502 | + | |
503 | + nread += n; | |
504 | + | |
505 | + if (n >= (int) nbyte) return nread; | |
506 | + | |
507 | + buf += n; | |
508 | + nbyte -= n; | |
509 | + } | |
510 | +} | |
511 | + | |
512 | +/* END FUNCTION: retry_read */ | |
513 | + | |
514 | +/* FUNCTION: retry_writev */ | |
515 | + | |
516 | +/* SYNOPSIS | |
517 | + * Keep calling the writev() system call with 'fd', 'iov', and 'iovcnt' | |
518 | + * until all the data is written out or an error occurs. | |
519 | + * END SYNOPSIS */ | |
520 | + | |
521 | +static int /* R: bytes written, or -1 on error */ | |
522 | +retry_writev ( | |
523 | + /* PARAMETERS */ | |
524 | + int fd, /* I: fd to write on */ | |
525 | + struct iovec *iov, /* U: iovec array base | |
526 | + * modified as data written */ | |
527 | + int iovcnt /* I: number of iovec entries */ | |
528 | + /* END PARAMETERS */ | |
529 | + ) | |
530 | +{ | |
531 | + /* VARIABLES */ | |
532 | + int n; /* return value from writev() */ | |
533 | + int i; /* loop counter */ | |
534 | + int written; /* bytes written so far */ | |
535 | + static int iov_max; /* max number of iovec entries */ | |
536 | + /* END VARIABLES */ | |
537 | + | |
538 | + /* initialization */ | |
539 | +#ifdef MAXIOV | |
540 | + iov_max = MAXIOV; | |
541 | +#else /* ! MAXIOV */ | |
542 | +# ifdef IOV_MAX | |
543 | + iov_max = IOV_MAX; | |
544 | +# else /* ! IOV_MAX */ | |
545 | + iov_max = 8192; | |
546 | +# endif /* ! IOV_MAX */ | |
547 | +#endif /* ! MAXIOV */ | |
548 | + written = 0; | |
549 | + | |
550 | + for (;;) { | |
551 | + | |
552 | + while (iovcnt && iov[0].iov_len == 0) { | |
553 | + iov++; | |
554 | + iovcnt--; | |
555 | + } | |
556 | + | |
557 | + if (!iovcnt) { | |
558 | + return written; | |
559 | + } | |
560 | + | |
561 | + n = writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt); | |
562 | + if (n == -1) { | |
563 | + if (errno == EINVAL && iov_max > 10) { | |
564 | + iov_max /= 2; | |
565 | + continue; | |
566 | + } | |
567 | + if (errno == EINTR) { | |
568 | + continue; | |
569 | + } | |
570 | + return -1; | |
571 | + } else { | |
572 | + written += n; | |
573 | + } | |
574 | + | |
575 | + for (i = 0; i < iovcnt; i++) { | |
576 | + if (iov[i].iov_len > (unsigned) n) { | |
577 | + iov[i].iov_base = (char *)iov[i].iov_base + n; | |
578 | + iov[i].iov_len -= n; | |
579 | + break; | |
580 | + } | |
581 | + n -= iov[i].iov_len; | |
582 | + iov[i].iov_len = 0; | |
583 | + } | |
584 | + | |
585 | + if (i == iovcnt) { | |
586 | + return written; | |
587 | + } | |
588 | + } | |
589 | + /* NOTREACHED */ | |
590 | +} | |
591 | + | |
592 | +/* END FUNCTION: retry_writev */ | |
593 | +#endif | |
594 | /* End of auths/pwcheck.c */ | |
595 | diff -urP exim-4.20.orig/src/auths/pwcheck.h exim-4.20/src/auths/pwcheck.h | |
596 | --- exim-4.20.orig/src/auths/pwcheck.h 2003-07-09 02:04:25.000000000 +0200 | |
597 | +++ exim-4.20/src/auths/pwcheck.h 2003-07-09 02:04:37.000000000 +0200 | |
598 | @@ -9,13 +9,18 @@ | |
599 | daemon. */ | |
600 | ||
601 | /* Error codes */ | |
602 | +/* OK - auth successful | |
603 | + NO - access denied | |
604 | + FAIL - [temporary] failure */ | |
605 | + | |
606 | ||
607 | #define PWCHECK_OK 0 | |
608 | -#define PWCHECK_BAD 1 | |
609 | +#define PWCHECK_NO 1 | |
610 | #define PWCHECK_FAIL 2 | |
611 | ||
612 | -/* Cyrus function for doing the business */ | |
613 | +/* Cyrus functions for doing the business */ | |
614 | ||
615 | extern int pwcheck_verify_password(const char *, const char *, const char **); | |
616 | +extern int saslauthd_verify_password(const char *, const char *, const char *, const char *, const char **); | |
617 | ||
618 | /* End of pwcheck.h */ | |
619 | diff -urP exim-4.20.orig/src/config.h.defaults exim-4.20/src/config.h.defaults | |
620 | --- exim-4.20.orig/src/config.h.defaults 2003-07-09 02:04:25.000000000 +0200 | |
621 | +++ exim-4.20/src/config.h.defaults 2003-07-09 02:04:37.000000000 +0200 | |
622 | @@ -23,6 +23,7 @@ | |
623 | #define CONFIGURE_FILE_USE_EUID | |
624 | #define CONFIGURE_FILE_USE_NODE | |
625 | #define CYRUS_PWCHECK_SOCKET | |
626 | +#define CYRUS_SASLAUTHD_SOCKET | |
627 | ||
628 | #define DEFAULT_CRYPT crypt | |
629 | #define DELIVER_IN_BUFFER_SIZE 8192 | |
630 | diff -urP exim-4.20.orig/src/EDITME exim-4.20/src/EDITME | |
631 | --- exim-4.20.orig/src/EDITME 2003-07-09 02:04:25.000000000 +0200 | |
632 | +++ exim-4.20/src/EDITME 2003-07-09 02:04:37.000000000 +0200 | |
633 | @@ -523,6 +523,20 @@ | |
634 | ||
635 | ||
636 | #------------------------------------------------------------------------------ | |
637 | +# Support for authentication via the Cyrus SASL saslauthd daemon is available. | |
638 | +# The Exim support, which is intented for use in conjunction with the SMTP AUTH | |
639 | +# facilities, is included only when requested by setting the following | |
640 | +# parameter to the location of the saslauthd daemon's socket directory. | |
641 | +# | |
642 | +# There is no need to install all of SASL on your system. You just need to run | |
643 | +# ./configure --with-saslauthd, cd to the saslauthd directory with sources, make | |
644 | +# and make install. You must create the socket directory (default /var/saslauthd) | |
645 | +# and chown it to exim's user and group. Once you have installed saslauthd, you | |
646 | +# should arrange for it to be started by root at boot time. | |
647 | + | |
648 | +CYRUS_SASLAUTHD_SOCKET=/var/lib/sasl2/mux | |
649 | + | |
650 | +#------------------------------------------------------------------------------ | |
651 | # TCP wrappers: If you want to use tcpwrappers from within Exim, uncomment | |
652 | # this setting. See the manual section entitled "Use of tcpwrappers" in the | |
653 | # chapter on building and installing Exim. | |
654 | diff -urP exim-4.20.orig/src/expand.c exim-4.20/src/expand.c | |
655 | --- exim-4.20.orig/src/expand.c 2003-07-09 02:04:25.000000000 +0200 | |
656 | +++ exim-4.20/src/expand.c 2003-07-09 02:04:37.000000000 +0200 | |
657 | @@ -1264,6 +1264,7 @@ | |
658 | radius: does RADIUS authentication | |
659 | ldapauth: does LDAP authentication | |
660 | pwcheck: does Cyrus SASL pwcheck authentication | |
661 | + saslauthd: does Cyrus SASL saslauthd authentication | |
662 | */ | |
663 | ||
664 | else if (Ustrcmp(name, "exists") == 0 | |
665 | @@ -1271,14 +1272,17 @@ | |
666 | || Ustrcmp(name, "pam") == 0 | |
667 | #endif /* SUPPORT_PAM */ | |
668 | #ifdef RADIUS_CONFIG_FILE | |
669 | - || Ustrcmp(name, "radius") == 0 | |
670 | - #endif /* RADIUS_CONFIG_FILE */ | |
671 | + || Ustrcmp(name, "radius") == 0 | |
672 | + #endif /* RADIUS_CONFIG_FILE */ | |
673 | #ifdef LOOKUP_LDAP | |
674 | || Ustrcmp(name, "ldapauth") == 0 | |
675 | #endif | |
676 | #ifdef CYRUS_PWCHECK_SOCKET | |
677 | - || Ustrcmp(name, "pwcheck") == 0 | |
678 | - #endif | |
679 | + || Ustrcmp(name, "pwcheck") == 0 | |
680 | + #endif | |
681 | + #ifdef CYRUS_SASLAUTHD_SOCKET | |
682 | + | Ustrcmp(name, "saslauthd") == 0 | |
683 | + #endif | |
684 | ) | |
685 | { | |
686 | uschar *sub; | |
687 | @@ -1306,7 +1310,7 @@ | |
688 | if (name[0] == 'p' && name[1] == 'a') | |
689 | rc = auth_call_pam(sub, &expand_string_message); | |
690 | #if defined(RADIUS_CONFIG_FILE) || defined(LOOKUP_LDAP) ||\ | |
691 | - defined(CYRUS_PWCHECK_SOCKET) | |
692 | + defined(CYRUS_PWCHECK_SOCKET) || defined(CYRUS_SASLAUTHD_SOCKET) | |
693 | else | |
694 | #endif | |
695 | #endif /* SUPPORT_PAM */ | |
696 | @@ -1314,7 +1318,7 @@ | |
697 | #ifdef RADIUS_CONFIG_FILE | |
698 | if (name[0] == 'r') | |
699 | rc = auth_call_radius(sub, &expand_string_message); | |
700 | - #if defined(LOOKUP_LDAP) || defined(CYRUS_PWCHECK_SOCKET) | |
701 | + #if defined(LOOKUP_LDAP) || defined(CYRUS_PWCHECK_SOCKET) || defined(CYRUS_SASLAUTHD_SOCKET) | |
702 | else | |
703 | #endif | |
704 | #endif /* RADIUS_CONFIG_FILE */ | |
705 | @@ -1323,16 +1327,24 @@ | |
706 | if (name[0] == 'l') | |
707 | rc = eldapauth_find((void *)(-1), NULL, sub, Ustrlen(sub), NULL, | |
708 | &expand_string_message); | |
709 | - #if defined(CYRUS_PWCHECK_SOCKET) | |
710 | + #if defined(CYRUS_PWCHECK_SOCKET) || defined(CYRUS_SASLAUTHD_SOCKET) | |
711 | else | |
712 | #endif | |
713 | #endif /* LOOKUP_LDAP */ | |
714 | ||
715 | #ifdef CYRUS_PWCHECK_SOCKET | |
716 | if (name[0] == 'p') | |
717 | - rc = auth_call_pwcheck(sub, &expand_string_message); | |
718 | + rc = auth_call_pwcheck(sub, &expand_string_message); | |
719 | + #if defined(CYRUS_SASLAUTHD_SOCKET) | |
720 | + else | |
721 | + #endif | |
722 | #endif /* CYRUS_PWCHECK_SOCKET */ | |
723 | ||
724 | + #ifdef CYRUS_SASLAUTHD_SOCKET | |
725 | + if (name[0] == 's') | |
726 | + rc = auth_call_saslauthd(sub, &expand_string_message); | |
727 | + #endif /* CYRUS_SASLAUTHD_SOCKET */ | |
728 | + | |
729 | if (rc == ERROR || rc == DEFER) return NULL; | |
730 | *yield = (rc == OK) == testfor; | |
731 | } | |
732 | diff -urP exim-4.20.orig/src/functions.h exim-4.20/src/functions.h | |
733 | --- exim-4.20.orig/src/functions.h 2003-07-09 02:04:25.000000000 +0200 | |
734 | +++ exim-4.20/src/functions.h 2003-07-09 02:04:37.000000000 +0200 | |
735 | @@ -42,6 +42,7 @@ | |
736 | extern int auth_b64decode(uschar *, uschar **); | |
737 | extern int auth_call_pam(uschar *, uschar **); | |
738 | extern int auth_call_pwcheck(uschar *, uschar **); | |
739 | +extern int auth_call_saslauthd(uschar *, uschar **); | |
740 | extern int auth_call_radius(uschar *, uschar **); | |
741 | extern int auth_get_data(uschar **, uschar *); | |
742 | extern int auth_get_no64_data(uschar **, uschar *); |