2 ** Copyright 2000-2006 Double Precision, Inc. See COPYING for
3 ** distribution information.
7 #include "authstaticlist.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,
34 static const char rcsid
[]="$Id: authdaemonlib.c,v 1.17 2006/01/22 03:33:24 mrsam Exp $";
36 static int s_connect(int sockfd
,
37 const struct sockaddr
*addr
,
39 time_t connect_timeout
)
46 setsockopt(sockfd
, SOL_SOCKET
, SOL_KEEPALIVE
,
47 (const char *)&dummy
, sizeof(dummy
));
57 setsockopt(sockfd
, SOL_SOCKET
, SOL_LINGER
,
58 (const char *)&l
, sizeof(l
));
63 ** If configuration says to use the kernel's timeout settings,
64 ** just call connect, and be done with it.
67 if (connect_timeout
== 0)
68 return ( connect(sockfd
, addr
, addr_s
));
70 /* Asynchronous connect with timeout. */
72 if (fcntl(sockfd
, F_SETFL
, O_NONBLOCK
) < 0) return (-1);
74 if ( connect(sockfd
, addr
, addr_s
) == 0)
76 /* That was easy, we're done. */
78 if (fcntl(sockfd
, F_SETFL
, 0) < 0) return (-1);
82 if (errno
!= EINPROGRESS
)
85 /* Wait for the connection to go through, until the timeout expires */
89 tv
.tv_sec
=connect_timeout
;
92 rc
=select(sockfd
+1, 0, &fdr
, 0, &tv
);
93 if (rc
< 0) return (-1);
95 if (!FD_ISSET(sockfd
, &fdr
))
103 socklen_t gslen
= sizeof(gserr
);
105 if (getsockopt(sockfd
, SOL_SOCKET
,
107 (char *)&gserr
, &gslen
)==0)
118 static int opensock()
120 int s
=socket(PF_UNIX
, SOCK_STREAM
, 0);
121 struct sockaddr_un skun
;
123 skun
.sun_family
=AF_UNIX
;
124 strcpy(skun
.sun_path
, AUTHDAEMONSOCK
);
128 perror("CRIT: authdaemon: socket() failed");
133 const char *p
=getenv("TIMEOUT_SOCK");
134 int n
=atoi(p
? p
:"0");
141 const char *p
=getenv("TIMEOUT_READ");
142 int n
=atoi(p
? p
:"0");
149 const char *p
=getenv("TIMEOUT_WRITE");
150 int n
=atoi(p
? p
:"0");
156 if (s_connect(s
, (const struct sockaddr
*)&skun
, sizeof(skun
),
159 perror("ERR: authdaemon: s_connect() failed");
160 if (errno
== ETIMEDOUT
|| errno
== ECONNREFUSED
)
161 fprintf(stderr
, "ERR: [Hint: perhaps authdaemond is not running?]\n");
168 static int writeauth(int fd
, const char *p
, unsigned pl
)
179 tv
.tv_sec
=TIMEOUT_WRITE
;
181 if (select(fd
+1, 0, &fds
, 0, &tv
) <= 0 || !FD_ISSET(fd
, &fds
))
184 if (n
<= 0) return (-1);
191 static void readauth(int fd
, char *p
, unsigned pl
, const char *term
)
193 time_t end_time
, curtime
;
194 unsigned len
= 0, tlen
= strlen(term
);
199 end_time
+= TIMEOUT_READ
;
208 if (curtime
>= end_time
)
213 tv
.tv_sec
=end_time
- curtime
;
215 if (select(fd
+1, &fds
, 0, 0, &tv
) <= 0 || !FD_ISSET(fd
, &fds
))
223 /* end-of-message detection for authpipe */
225 if (len
>= tlen
&& strncmp(p
-tlen
, term
, tlen
) == 0)
227 else if (len
== 5 && strncmp(p
-5, "FAIL\n", 5) == 0)
233 int _authdaemondopasswd(int wrfd
, int rdfd
, char *buffer
, int bufsiz
)
235 if (writeauth(wrfd
, buffer
, strlen(buffer
)))
238 readauth(rdfd
, buffer
, bufsiz
, "\n");
240 if (strcmp(buffer
, "OK\n"))
248 int authdaemondopasswd(char *buffer
, int bufsiz
)
255 rc
= _authdaemondopasswd(s
, s
, buffer
, bufsiz
);
260 int _authdaemondo(int wrfd
, int rdfd
, const char *authreq
,
261 int (*func
)(struct authinfo
*, void *), void *arg
)
268 if (writeauth(wrfd
, authreq
, strlen(authreq
)))
273 readauth(rdfd
, buf
, sizeof(buf
), "\n.\n");
274 memset(&a
, 0, sizeof(a
));
285 if (strcmp(p
, ".") == 0)
287 return ( (*func
)(&a
, arg
));
289 if (strcmp(p
, "FAIL") == 0)
302 if (strcmp(p
, "USERNAME") == 0)
304 else if (strcmp(p
, "UID") == 0)
309 else if (strcmp(p
, "GID") == 0)
311 a
.sysgroupid
=atol(r
);
313 else if (strcmp(p
, "HOME") == 0)
317 else if (strcmp(p
, "ADDRESS") == 0)
321 else if (strcmp(p
, "NAME") == 0)
325 else if (strcmp(p
, "MAILDIR") == 0)
329 else if (strcmp(p
, "QUOTA") == 0)
333 else if (strcmp(p
, "PASSWD") == 0)
337 else if (strcmp(p
, "PASSWD2") == 0)
341 else if (strcmp(p
, "OPTIONS") == 0)
351 int authdaemondo(const char *authreq
,
352 int (*func
)(struct authinfo
*, void *), void *arg
)
361 rc
= _authdaemondo(s
, s
, authreq
, func
, arg
);
366 void auth_daemon_cleanup()
376 #define getauthc(fd,eg) ((eg)->buf_left-- ? \
377 (unsigned char)*((eg)->buf_ptr)++:\
378 fillgetauthc((fd),(eg)))
380 static int fillgetauthc(int fd
, struct enum_getch
*eg
)
382 time_t end_time
, curtime
;
394 if (curtime
>= end_time
)
399 tv
.tv_sec
=end_time
- curtime
;
401 if (select(fd
+1, &fds
, 0, 0, &tv
) <= 0 || !FD_ISSET(fd
, &fds
))
404 n
=read(fd
, eg
->buffer
, sizeof(eg
->buffer
));
408 eg
->buf_ptr
=eg
->buffer
;
412 return (unsigned char)*(eg
->buf_ptr
)++;
417 static int readline(int fd
, struct enum_getch
*eg
,
426 int ch
=getauthc(fd
, eg
);
439 int _auth_enumerate(int wrfd
, int rdfd
,
440 void(*cb_func
)(const char *name
,
449 static char cmd
[]="ENUMERATE\n";
450 struct enum_getch eg
;
451 char linebuf
[BUFSIZ
];
453 if (writeauth(wrfd
, cmd
, sizeof(cmd
)-1))
460 while (readline(rdfd
, &eg
, linebuf
, sizeof(linebuf
)) == 0)
470 if (strcmp(linebuf
, ".") == 0)
472 (*cb_func
)(NULL
, 0, 0, NULL
, NULL
, NULL
, void_arg
);
476 p
=strchr(linebuf
, '#');
479 p
=strchr(linebuf
, '\t');
486 uid
=libmail_atouid_t(p
);
491 gid
=libmail_atogid_t(p
);
517 (*cb_func
)(name
, uid
, gid
, homedir
,
518 maildir
, options
, void_arg
);
526 void auth_enumerate( void(*cb_func
)(const char *name
,
540 _auth_enumerate(s
, s
, cb_func
, void_arg
);