authdaemond.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:11k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 2000 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. #include "config.h"
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <sys/socket.h>
  9. #include <sys/un.h>
  10. #include <sys/time.h>
  11. #include <sys/wait.h>
  12. #include <unistd.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <signal.h>
  17. #include <fcntl.h>
  18. #include <ctype.h>
  19. #include <syslog.h>
  20. #include "numlib/numlib.h"
  21. #include "liblock/config.h"
  22. #include "liblock/liblock.h"
  23. #include "auth.h"
  24. #include "authmod.h"
  25. #include "authdaemonrc.h"
  26. static const char rcsid[]="$Id: authdaemond.c,v 1.7 2000/05/04 01:31:31 mrsam Exp $";
  27. #ifndef SOMAXCONN
  28. #define SOMAXCONN 5
  29. #endif
  30. #if HAVE_HMACLIB
  31. #include        "../libhmac/hmac.h"
  32. #include        "cramlib.h"
  33. #endif
  34. #include "authstaticlist.h"
  35. /* First, prototype the functions */
  36. #define AUTHSTATIC(name, func, prefunc, cleanupfunc) 
  37. extern char *func(const char *, const char *, char *, int, 
  38. void (*)(struct authinfo *, void *), void *); 
  39. extern int prefunc(const char *, const char *, 
  40. int (*)(struct authinfo *, void *), void *arg); 
  41. extern void cleanupfunc();
  42. DAEMON_STATIC_LIST
  43. #undef  AUTHSTATIC
  44. /* Now, we can build the list */
  45. #define AUTHSTATIC(name, func, prefunc, cleanupfunc) 
  46. { name, func, prefunc, cleanupfunc, 0},
  47. struct authstaticinfo authstaticlist[] = {
  48. DAEMON_STATIC_LIST
  49.         {0, 0, 0, 0} };
  50. static char *authmodulelist;
  51. static unsigned ndaemons;
  52. static int mksocket()
  53. {
  54. int fd=socket(PF_UNIX, SOCK_STREAM, 0);
  55. struct sockaddr_un skun;
  56. if (fd < 0) return (-1);
  57. skun.sun_family=AF_UNIX;
  58. strcpy(skun.sun_path, AUTHDAEMONSOCK);
  59. strcat(skun.sun_path, ".tmp");
  60. unlink(skun.sun_path);
  61. if (bind(fd, (const struct sockaddr *)&skun, sizeof(skun)) ||
  62. listen(fd, SOMAXCONN) ||
  63. chmod(skun.sun_path, 0777) ||
  64. rename(skun.sun_path, AUTHDAEMONSOCK) ||
  65. fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
  66. {
  67. perror(AUTHDAEMONSOCK);
  68. close(fd);
  69. return (-1);
  70. }
  71. return (fd);
  72. }
  73. static int readconfig()
  74. {
  75. char buf[BUFSIZ];
  76. FILE *fp;
  77. char *modlist=0;
  78. unsigned daemons=1;
  79. if ((fp=fopen(AUTHDAEMONRC, "r")) == NULL)
  80. {
  81. perror(AUTHDAEMONRC);
  82. return (-1);
  83. }
  84. while (fgets(buf, sizeof(buf), fp))
  85. {
  86. char *p=strchr(buf, 'n'), *q;
  87. if (!p)
  88. {
  89. int c;
  90. while ((c=getc(fp)) >= 0 && c != 'n')
  91. ;
  92. }
  93. else *p=0;
  94. if ((p=strchr(buf, '#')) != 0) *p=0;
  95. for (p=buf; *p; p++)
  96. if (!isspace((int)(unsigned char)*p))
  97. break;
  98. if (*p == 0) continue;
  99. if ((p=strchr(buf, '=')) == 0)
  100. {
  101. fprintf(stderr, "Bad line in %s: %sn",
  102. AUTHDAEMONRC, buf);
  103. fclose(fp);
  104. if (modlist)
  105. free(modlist);
  106. return (-1);
  107. }
  108. *p++=0;
  109. while (*p && isspace((int)(unsigned char)*p))
  110. ++p;
  111. if (*p == '"')
  112. {
  113. ++p;
  114. q=strchr(p, '"');
  115. if (q) *q=0;
  116. }
  117. if (strcmp(buf, "authmodulelist") == 0)
  118. {
  119. if (modlist)
  120. free(modlist);
  121. modlist=strdup(p);
  122. if (!modlist)
  123. {
  124. perror("malloc");
  125. fclose(fp);
  126. return (-1);
  127. }
  128. continue;
  129. }
  130. if (strcmp(buf, "daemons") == 0)
  131. {
  132. daemons=atoi(p);
  133. continue;
  134. }
  135. }
  136. fclose(fp);
  137. if (daemons <= 0)
  138. daemons=1;
  139. syslog(LOG_INFO, "authdaemon: modules="%s", daemons=%un",
  140. modlist ? modlist:AUTHDAEMONMODULELIST,
  141. daemons);
  142. ndaemons=daemons;
  143. if (authmodulelist) free(authmodulelist);
  144. authmodulelist=modlist;
  145. return (0);
  146. }
  147. static char buf[BUFSIZ];
  148. static char *readptr;
  149. static int readleft;
  150. static char *writeptr;
  151. static int writeleft;
  152. static int getauthc(int fd)
  153. {
  154. fd_set fds;
  155. struct timeval tv;
  156. if (readleft--)
  157. return ( (int)(unsigned char)*readptr++ );
  158. readleft=0;
  159. FD_ZERO(&fds);
  160. FD_SET(fd, &fds);
  161. tv.tv_sec=10;
  162. tv.tv_usec=0;
  163. if (select(fd+1, &fds, 0, 0, &tv) <= 0 ||
  164. !FD_ISSET(fd, &fds))
  165. return (EOF);
  166. readleft=read(fd, buf, sizeof(buf));
  167. readptr=buf;
  168. if (readleft <= 0)
  169. {
  170. readleft=0;
  171. return (EOF);
  172. }
  173. --readleft;
  174. return ( (int)(unsigned char)*readptr++ );
  175. }
  176. static int writeauth(int fd, const char *p, unsigned pl)
  177. {
  178. fd_set fds;
  179. struct timeval tv;
  180. while (pl)
  181. {
  182. int n;
  183. FD_ZERO(&fds);
  184. FD_SET(fd, &fds);
  185. tv.tv_sec=10;
  186. tv.tv_usec=0;
  187. if (select(fd+1, 0, &fds, 0, &tv) <= 0 ||
  188. !FD_ISSET(fd, &fds))
  189. return (-1);
  190. n=write(fd, p, pl);
  191. if (n <= 0) return (-1);
  192. p += n;
  193. pl -= n;
  194. }
  195. return (0);
  196. }
  197. static int writeauthflush(int fd)
  198. {
  199. if (writeptr > buf)
  200. {
  201. if (writeauth(fd, buf, writeptr - buf))
  202. return (-1);
  203. }
  204. writeptr=buf;
  205. writeleft=sizeof(buf);
  206. return (0);
  207. }
  208. static int writeauthbuf(int fd, const char *p, unsigned pl)
  209. {
  210. unsigned n;
  211. while (pl)
  212. {
  213. if (pl < writeleft)
  214. {
  215. memcpy(writeptr, p, pl);
  216. writeptr += pl;
  217. writeleft -= pl;
  218. return (0);
  219. }
  220. if (writeauthflush(fd)) return (-1);
  221. n=pl;
  222. if (n > writeleft) n=writeleft;
  223. memcpy(writeptr, p, n);
  224. p += n;
  225. writeptr += n;
  226. writeleft -= n;
  227. pl -= n;
  228. }
  229. return (0);
  230. }
  231. static int writeenvval(int fd, const char *env, const char *val)
  232. {
  233. if (writeauthbuf(fd, env, strlen(env)) ||
  234. writeauthbuf(fd, "=", 1) ||
  235. writeauthbuf(fd, val, strlen(val)) ||
  236. writeauthbuf(fd, "n", 1))
  237. return (-1);
  238. return (0);
  239. }
  240. static int printauth(struct authinfo *authinfo, void *vp)
  241. {
  242. int fd= *(int *)vp;
  243. char buf2[NUMBUFSIZE];
  244. writeptr=buf;
  245. writeleft=sizeof(buf);
  246. if (authinfo->sysusername)
  247. if (writeenvval(fd, "USERNAME", authinfo->sysusername))
  248. return (1);
  249. if (authinfo->sysuserid)
  250. if (writeenvval(fd, "UID", str_uid_t(*authinfo->sysuserid,
  251. buf2)))
  252. return (1);
  253. if (writeenvval(fd, "GID", str_uid_t(authinfo->sysgroupid, buf2)))
  254. return (1);
  255. if (writeenvval(fd, "HOME", authinfo->homedir))
  256. return (1);
  257. if (authinfo->address)
  258. if (writeenvval(fd, "ADDRESS", authinfo->address))
  259. return (1);
  260. if (authinfo->fullname)
  261. if (writeenvval(fd, "NAME", authinfo->fullname))
  262. return (1);
  263. if (authinfo->maildir)
  264. if (writeenvval(fd, "MAILDIR", authinfo->maildir))
  265. return (1);
  266. if (authinfo->quota)
  267. if (writeenvval(fd, "QUOTA", authinfo->quota))
  268. return (1);
  269. if (authinfo->passwd)
  270. if (writeenvval(fd, "PASSWD", authinfo->passwd))
  271. return (1);
  272. if (authinfo->clearpasswd)
  273. if (writeenvval(fd, "PASSWD2", authinfo->clearpasswd))
  274. return (1);
  275. if (writeauthbuf(fd, ".n", 2) || writeauthflush(fd))
  276. return (1);
  277. return (0);
  278. }
  279. static void printauth_void(struct authinfo *authinfo, void *vp)
  280. {
  281. printauth(authinfo, vp);
  282. }
  283. static const char *authnextptr;
  284. static int authnexti;
  285. static void authbegin()
  286. {
  287. authnextptr=authmodulelist;
  288. authnexti=0;
  289. }
  290. static int authnext()
  291. {
  292. if (authmodulelist == 0)
  293. {
  294. if (authstaticlist[authnexti].auth_name == 0)
  295. return (-1);
  296. return (authnexti++);
  297. }
  298. for (;;)
  299. {
  300. int i;
  301. while (*authnextptr &&
  302. isspace((int)(unsigned char)*authnextptr))
  303. ++authnextptr;
  304. if (*authnextptr == 0) return (-1);
  305. for (i=0; authnextptr[i] &&
  306. !isspace((int)(unsigned char)authnextptr[i]); i++)
  307. ;
  308. for (authnexti=0; authstaticlist[authnexti].auth_name;
  309. authnexti++)
  310. if (strncmp(authstaticlist[authnexti].auth_name,
  311. authnextptr, i) == 0 &&
  312. authstaticlist[authnexti].auth_name[i] == 0)
  313. {
  314. authnextptr += i;
  315. return (authnexti);
  316. }
  317. authnextptr += i;
  318. }
  319. }
  320. static void pre(int fd, char *prebuf)
  321. {
  322. char *p=strchr(prebuf, ' ');
  323. char *service;
  324. int i;
  325. if (!p) return;
  326. *p++=0;
  327. while (*p == ' ') ++p;
  328. service=p;
  329. p=strchr(p, ' ');
  330. if (!p) return;
  331.         *p++=0;
  332.         while (*p == ' ')     ++p;
  333. for (authbegin(); (i=authnext()) >= 0; )
  334. {
  335. int rc;
  336. if (strcmp(prebuf, ".") && strcmp(prebuf,
  337. authstaticlist[i].auth_name))
  338. continue;
  339. rc=(*authstaticlist[i].auth_prefunc)(p, service,
  340.                         &printauth, &fd);
  341. if (rc >= 0) return;
  342. }
  343. writeauth(fd, "FAILn", 5);
  344. }
  345. static void auth(int fd, char *p)
  346. {
  347. char *service;
  348. char *authtype;
  349. int i;
  350. char *pp;
  351. service=p;
  352. if ((p=strchr(p, 'n')) == 0) return;
  353. *p++=0;
  354. authtype=p;
  355. if ((p=strchr(p, 'n')) == 0) return;
  356. *p++=0;
  357. pp=malloc(strlen(p)+1);
  358. if (!pp)
  359. {
  360. syslog(LOG_CRIT, "authdaemon: malloc() failed: %m");
  361. return;
  362. }
  363. for (authbegin(); (i=authnext()) >= 0; )
  364. {
  365. char *q=(*authstaticlist[i].auth_func)(service, authtype,
  366. strcpy(pp, p), 1, &printauth_void, &fd);
  367. if (q)
  368. {
  369. free(q);
  370. free(pp);
  371. return;
  372. }
  373. if (errno != EPERM)
  374. {
  375. free(pp);
  376. return; /* Temporary error */
  377. }
  378. }
  379. writeauth(fd, "FAILn", 5);
  380. free(pp);
  381. }
  382. static void doauth(int fd)
  383. {
  384. char buf[BUFSIZ];
  385. int i, ch;
  386. char *p;
  387. readleft=0;
  388. for (i=0; (ch=getauthc(fd)) != 'n'; i++)
  389. {
  390. if (ch < 0 || i >= sizeof(buf)-2)
  391. return;
  392. buf[i]=ch;
  393. }
  394. buf[i]=0;
  395. for (p=buf; *p; p++)
  396. {
  397. if (*p == ' ')
  398. {
  399. *p++=0;
  400. while (*p == ' ') ++p;
  401. break;
  402. }
  403. }
  404. if (strcmp(buf, "PRE") == 0)
  405. {
  406. pre(fd, p);
  407. return;
  408. }
  409. if (strcmp(buf, "AUTH") == 0)
  410. {
  411. int j;
  412. i=atoi(p);
  413. if (i < 0 || i >= sizeof(buf)) return;
  414. for (j=0; j<i; j++)
  415. {
  416. ch=getauthc(fd);
  417. if (ch < 0) return;
  418. buf[j]=ch;
  419. }
  420. buf[j]=0;
  421. auth(fd, buf);
  422. }
  423. }
  424. static int sighup_pipe= -1;
  425. static RETSIGTYPE sighup(int n)
  426. {
  427. if (sighup_pipe >= 0)
  428. {
  429. close(sighup_pipe);
  430. sighup_pipe= -1;
  431. }
  432. signal(SIGHUP, sighup);
  433. #if RETSIGTYPE != void
  434. return (1);
  435. #endif
  436. }
  437. static int sigterm_received=0;
  438. static RETSIGTYPE sigterm(int n)
  439. {
  440. sigterm_received=1;
  441. if (sighup_pipe >= 0)
  442. {
  443. close(sighup_pipe);
  444. sighup_pipe= -1;
  445. }
  446. else
  447. {
  448. kill(0, SIGTERM);
  449. _exit(0);
  450. }
  451. #if RETSIGTYPE != void
  452. return (0);
  453. #endif
  454. }
  455. static int startchildren(int *pipefd)
  456. {
  457. unsigned i;
  458. pid_t p;
  459. if (ndaemons <= 1)
  460. {
  461. return (0); /* No need for kids */
  462. }
  463. for (i=0; i<ndaemons; i++)
  464. {
  465. p=fork();
  466. if (p == -1)
  467. {
  468. syslog(LOG_CRIT, "authdaemon: fork() failed: %m");
  469. if (i == 0)
  470. ndaemons=1; /* Assume 1 daemon */
  471. return (0);
  472. }
  473. if (p == 0)
  474. {
  475. sighup_pipe= -1;
  476. close(pipefd[1]);
  477. signal(SIGHUP, SIG_DFL);
  478. signal(SIGTERM, SIG_DFL);
  479. return (1);
  480. }
  481. }
  482. return (0);
  483. }
  484. static int killchildren(int *pipefd)
  485. {
  486. int waitstat;
  487. while (wait(&waitstat) >= 0 || errno != ECHILD)
  488. ;
  489. if (pipe(pipefd))
  490. {
  491. syslog(LOG_CRIT, "authdaemon: pipe() failed: %m");
  492. return (-1);
  493. }
  494. return (0);
  495. }
  496. int start()
  497. {
  498. int s;
  499. int lockfd;
  500. int fd;
  501. int pipefd[2];
  502. int do_child;
  503. if ((lockfd=ll_daemon_start(AUTHDAEMONLOCK)) < 0)
  504. return (1);
  505. if (pipe(pipefd))
  506. {
  507. perror("pipe");
  508. return (1);
  509. }
  510. if (readconfig())
  511. {
  512. close(pipefd[0]);
  513. close(pipefd[1]);
  514. return (1);
  515. }
  516. s=mksocket();
  517. if (s < 0)
  518. {
  519. perror(AUTHDAEMONSOCK);
  520. close(pipefd[0]);
  521. close(pipefd[1]);
  522. return (1);
  523. }
  524. signal(SIGPIPE, SIG_IGN);
  525. signal(SIGHUP, sighup);
  526. signal(SIGTERM, sigterm);
  527. ll_daemon_started(AUTHDAEMONPID, lockfd);
  528. sighup_pipe= pipefd[1];
  529. do_child=startchildren(pipefd);
  530. for (;;)
  531. {
  532. struct sockaddr saddr;
  533. int saddr_len;
  534. fd_set fds;
  535. FD_ZERO(&fds);
  536. FD_SET(pipefd[0], &fds);
  537. if (do_child || ndaemons == 1)
  538. FD_SET(s, &fds);
  539. if (select( (s > pipefd[0] ? s:pipefd[0])+1,
  540. &fds, 0, 0, 0) <= 0)
  541. continue;
  542. if (FD_ISSET(pipefd[0], &fds))
  543. {
  544. close(pipefd[0]);
  545. if (do_child)
  546. return (0); /* Parent died */
  547. readconfig();
  548. while (killchildren(pipefd))
  549. sleep(5);
  550. if (sigterm_received)
  551. return (0);
  552. sighup_pipe=pipefd[1];
  553. do_child=startchildren(pipefd);
  554. continue;
  555. }
  556. if (!FD_ISSET(s, &fds))
  557. continue;
  558. saddr_len=sizeof(saddr);
  559. if ((fd=accept(s, &saddr, &saddr_len)) < 0)
  560. continue;
  561. if (fcntl(fd, F_SETFL, 0) < 0)
  562. {
  563. syslog(LOG_CRIT, "authdaemon: fcntl() failed: %m");
  564. }
  565. else
  566. doauth(fd);
  567. close(fd);
  568. }
  569. }
  570. int main(int argc, char **argv)
  571. {
  572. if (argc > 1)
  573. {
  574. if (strcmp(argv[1], "start") == 0)
  575. {
  576. exit(start());
  577. }
  578. if (strcmp(argv[1], "stop") == 0)
  579. {
  580. exit(ll_daemon_stop(AUTHDAEMONLOCK, AUTHDAEMONPID));
  581. }
  582. if (strcmp(argv[1], "restart") == 0)
  583. {
  584. exit(ll_daemon_restart(AUTHDAEMONLOCK, AUTHDAEMONPID));
  585. }
  586. }
  587. fprintf(stderr, "Usage: %s start|stop|restartn", argv[0]);
  588. exit (1);
  589. return (0);
  590. }