2 ** Copyright 2000-2006 Double Precision, Inc. See COPYING for
3 ** distribution information.
7 #include "courierauthstaticlist.h"
8 #include "courierauthsasl.h"
16 #include <sys/types.h>
17 #include <sys/socket.h>
21 #include <sys/select.h>
27 #include "authdaemonrc.h"
28 #include "numlib/numlib.h"
30 static int TIMEOUT_SOCK
=10,
35 static int s_connect(int sockfd
,
36 const struct sockaddr
*addr
,
38 time_t connect_timeout
)
45 setsockopt(sockfd
, SOL_SOCKET
, SOL_KEEPALIVE
,
46 (const char *)&dummy
, sizeof(dummy
));
56 setsockopt(sockfd
, SOL_SOCKET
, SOL_LINGER
,
57 (const char *)&l
, sizeof(l
));
62 ** If configuration says to use the kernel's timeout settings,
63 ** just call connect, and be done with it.
66 if (connect_timeout
== 0)
67 return ( connect(sockfd
, addr
, addr_s
));
69 /* Asynchronous connect with timeout. */
71 if (fcntl(sockfd
, F_SETFL
, O_NONBLOCK
) < 0) return (-1);
73 if ( connect(sockfd
, addr
, addr_s
) == 0)
75 /* That was easy, we're done. */
77 if (fcntl(sockfd
, F_SETFL
, 0) < 0) return (-1);
81 if (errno
!= EINPROGRESS
)
84 /* Wait for the connection to go through, until the timeout expires */
88 tv
.tv_sec
=connect_timeout
;
91 rc
=select(sockfd
+1, 0, &fdr
, 0, &tv
);
92 if (rc
< 0) return (-1);
94 if (!FD_ISSET(sockfd
, &fdr
))
102 socklen_t gslen
= sizeof(gserr
);
104 if (getsockopt(sockfd
, SOL_SOCKET
,
106 (char *)&gserr
, &gslen
)==0)
117 static int opensock()
119 int s
=socket(PF_UNIX
, SOCK_STREAM
, 0);
120 struct sockaddr_un skun
;
122 skun
.sun_family
=AF_UNIX
;
123 strcpy(skun
.sun_path
, AUTHDAEMONSOCK
);
127 perror("CRIT: authdaemon: socket() failed");
132 const char *p
=getenv("TIMEOUT_SOCK");
133 int n
=atoi(p
? p
:"0");
140 const char *p
=getenv("TIMEOUT_READ");
141 int n
=atoi(p
? p
:"0");
148 const char *p
=getenv("TIMEOUT_WRITE");
149 int n
=atoi(p
? p
:"0");
155 if (s_connect(s
, (const struct sockaddr
*)&skun
, sizeof(skun
),
158 perror("ERR: authdaemon: s_connect() failed");
159 if (errno
== ETIMEDOUT
|| errno
== ECONNREFUSED
)
160 fprintf(stderr
, "ERR: [Hint: perhaps authdaemond is not running?]\n");
167 static int writeauth(int fd
, const char *p
, unsigned pl
)
178 tv
.tv_sec
=TIMEOUT_WRITE
;
180 if (select(fd
+1, 0, &fds
, 0, &tv
) <= 0 || !FD_ISSET(fd
, &fds
))
183 if (n
<= 0) return (-1);
190 static void readauth(int fd
, char *p
, unsigned pl
, const char *term
)
192 time_t end_time
, curtime
;
193 unsigned len
= 0, tlen
= strlen(term
);
198 end_time
+= TIMEOUT_READ
;
207 if (curtime
>= end_time
)
212 tv
.tv_sec
=end_time
- curtime
;
214 if (select(fd
+1, &fds
, 0, 0, &tv
) <= 0 || !FD_ISSET(fd
, &fds
))
222 /* end-of-message detection for authpipe */
224 if (len
>= tlen
&& strncmp(p
-tlen
, term
, tlen
) == 0)
226 else if (len
== 5 && strncmp(p
-5, "FAIL\n", 5) == 0)
232 int _authdaemondopasswd(int wrfd
, int rdfd
, char *buffer
, int bufsiz
)
234 if (writeauth(wrfd
, buffer
, strlen(buffer
)))
237 readauth(rdfd
, buffer
, bufsiz
, "\n");
239 if (strcmp(buffer
, "OK\n"))
247 int authdaemondopasswd(char *buffer
, int bufsiz
)
254 rc
= _authdaemondopasswd(s
, s
, buffer
, bufsiz
);
259 int _authdaemondo(int wrfd
, int rdfd
, const char *authreq
,
260 int (*func
)(struct authinfo
*, void *), void *arg
)
267 if (writeauth(wrfd
, authreq
, strlen(authreq
)))
272 readauth(rdfd
, buf
, sizeof(buf
), "\n.\n");
273 memset(&a
, 0, sizeof(a
));
284 if (strcmp(p
, ".") == 0)
286 return ( (*func
)(&a
, arg
));
288 if (strcmp(p
, "FAIL") == 0)
301 if (strcmp(p
, "USERNAME") == 0)
303 else if (strcmp(p
, "UID") == 0)
308 else if (strcmp(p
, "GID") == 0)
310 a
.sysgroupid
=atol(r
);
312 else if (strcmp(p
, "HOME") == 0)
316 else if (strcmp(p
, "ADDRESS") == 0)
320 else if (strcmp(p
, "NAME") == 0)
324 else if (strcmp(p
, "MAILDIR") == 0)
328 else if (strcmp(p
, "QUOTA") == 0)
332 else if (strcmp(p
, "PASSWD") == 0)
336 else if (strcmp(p
, "PASSWD2") == 0)
340 else if (strcmp(p
, "OPTIONS") == 0)
350 int authdaemondo(const char *authreq
,
351 int (*func
)(struct authinfo
*, void *), void *arg
)
360 rc
= _authdaemondo(s
, s
, authreq
, func
, arg
);
365 void auth_daemon_cleanup()
375 #define getauthc(fd,eg) ((eg)->buf_left-- ? \
376 (unsigned char)*((eg)->buf_ptr)++:\
377 fillgetauthc((fd),(eg)))
379 static int fillgetauthc(int fd
, struct enum_getch
*eg
)
381 time_t end_time
, curtime
;
393 if (curtime
>= end_time
)
398 tv
.tv_sec
=end_time
- curtime
;
400 if (select(fd
+1, &fds
, 0, 0, &tv
) <= 0 || !FD_ISSET(fd
, &fds
))
403 n
=read(fd
, eg
->buffer
, sizeof(eg
->buffer
));
407 eg
->buf_ptr
=eg
->buffer
;
411 return (unsigned char)*(eg
->buf_ptr
)++;
416 static int readline(int fd
, struct enum_getch
*eg
,
425 int ch
=getauthc(fd
, eg
);
438 int _auth_enumerate(int wrfd
, int rdfd
,
439 void(*cb_func
)(const char *name
,
448 static char cmd
[]="ENUMERATE\n";
449 struct enum_getch eg
;
450 char linebuf
[BUFSIZ
];
452 if (writeauth(wrfd
, cmd
, sizeof(cmd
)-1))
459 while (readline(rdfd
, &eg
, linebuf
, sizeof(linebuf
)) == 0)
469 if (strcmp(linebuf
, ".") == 0)
471 (*cb_func
)(NULL
, 0, 0, NULL
, NULL
, NULL
, void_arg
);
475 p
=strchr(linebuf
, '#');
478 p
=strchr(linebuf
, '\t');
485 uid
=libmail_atouid_t(p
);
490 gid
=libmail_atogid_t(p
);
516 (*cb_func
)(name
, uid
, gid
, homedir
,
517 maildir
, options
, void_arg
);
525 void auth_enumerate( void(*cb_func
)(const char *name
,
539 _auth_enumerate(s
, s
, cb_func
, void_arg
);