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

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 1999 Double Precision, Inc.  See COPYING for
  3. ** distribution information.
  4. */
  5. #include "config.h"
  6. #include "logincache.h"
  7. #include "numlib/numlib.h"
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <signal.h>
  12. #include <pwd.h>
  13. #if HAVE_UNISTD_H
  14. #include <unistd.h>
  15. #endif
  16. #include <sys/types.h>
  17. #if HAVE_SYS_STAT_H
  18. #include <sys/stat.h>
  19. #endif
  20. #if HAVE_SYS_WAIT_H
  21. #include <sys/wait.h>
  22. #endif
  23. #if HAVE_FCNTL_H
  24. #include <fcntl.h>
  25. #endif
  26. #if HAVE_SYSLOG_H
  27. #include <syslog.h>
  28. #else
  29. #define syslog(a,b)
  30. #endif
  31. #include "sqwebmail.h"
  32. static const char rcsid[]="$Id: logincache.c,v 1.9 2000/03/16 05:16:50 mrsam Exp $";
  33. #ifndef CACHEDIR
  34. /* Disabled */
  35. void init_login_cache(time_t a)
  36. {
  37. a=a;
  38. }
  39. void prepare_login_cache()
  40. {
  41. }
  42. void save_login_cache(const char *a, time_t b)
  43. {
  44. a=a;
  45. b=b;
  46. }
  47. void cancel_login_cache()
  48. {
  49. }
  50. int check_login_cache(const char *a, time_t b)
  51. {
  52. a=a;
  53. b=b;
  54. return (-1);
  55. }
  56. #else
  57. /* Need to cache the following environment variables */
  58. static const char * const authvars[] = { "AUTHADDR", "AUTHFULLNAME", 0 };
  59. static time_t expinterval;
  60. void init_login_cache(time_t n)
  61. {
  62. expinterval=n;
  63. }
  64. char *create_cache_name(const char *userid, time_t login_time)
  65. {
  66. int l;
  67. char buf[NUMBUFSIZE];
  68. const char *p;
  69. char *q;
  70. char *f, *g;
  71. login_time /= expinterval;
  72. l=1;
  73. for (p=userid; *p; p++)
  74. {
  75. ++l;
  76. if (*p == '/' || *p == '+' || *p < ' ' || *p >= 127)
  77. p += 2;
  78. }
  79. g=malloc(l);
  80. if (!g)
  81. {
  82. perror("malloc");
  83. enomem();
  84. }
  85. q=g;
  86. while (*userid)
  87. {
  88. if (*userid == '/' || *userid == '+' || *userid < ' '
  89. || *userid >= 127)
  90. {
  91. static char xdigit[]="0123456789ABCDEF";
  92. *q++ = '+';
  93. *q++ = xdigit[ (*userid >> 4) & 15 ];
  94. *q++ = xdigit[ (*userid) & 15 ];
  95. }
  96. else
  97. *q++ = *userid;
  98. ++userid;
  99. }
  100. *q=0;
  101. l=sizeof(CACHEDIR "//xx/");
  102. l += strlen(str_time_t( login_time, buf)) + strlen(g);
  103. f=malloc(l);
  104. if (!f)
  105. {
  106. perror("malloc");
  107. enomem();
  108. }
  109. strcat(strcat(strcpy(f, CACHEDIR "/"), buf), "/");
  110. strncpy(buf, g, 2);
  111. buf[2]=0;
  112. while (strlen(buf) < 2) strcat(buf, "+");
  113. strcat(strcat(strcat(f, buf), "/"), g);
  114. free(g);
  115. return (f);
  116. }
  117. static pid_t childproc= -1;
  118. static int childpipe;
  119. void prepare_login_cache()
  120. {
  121. int pipefd[2];
  122. char buf[2048];
  123. int i, j;
  124. char *userid, *login_time, *data;
  125. time_t login_time_n;
  126. char *f;
  127. FILE *fp;
  128. if (pipe(pipefd) < 0)
  129. {
  130. perror("pipe");
  131. enomem();
  132. }
  133. while ((childproc=fork()) < 0)
  134. {
  135. sleep(5);
  136. }
  137. if (childproc)
  138. {
  139. close(pipefd[0]);
  140. childpipe=pipefd[1];
  141. return;
  142. }
  143. close(pipefd[1]);
  144. i=0;
  145. for (;;)
  146. {
  147. if (i >= sizeof(buf)-1)
  148. {
  149. close(pipefd[0]);
  150. /* Problems */
  151. syslog(LOG_DAEMON | LOG_CRIT,
  152. "sqwebmail: Max cache buffer overflow.");
  153. return;
  154. }
  155. j=read(pipefd[0], buf+i, sizeof(buf)-1-i);
  156. if (j < 0)
  157. {
  158. syslog(LOG_DAEMON | LOG_CRIT,
  159. "sqwebmail: Cache create failure.");
  160. exit(1);
  161. }
  162. if (j == 0) break;
  163. i += j;
  164. }
  165. close(pipefd[0]);
  166. buf[i]=0;
  167. {
  168. struct passwd *pwd=getpwnam(CACHEOWNER);
  169. if (!pwd || setgid(pwd->pw_gid) || setuid(pwd->pw_uid))
  170. {
  171. syslog(LOG_DAEMON | LOG_CRIT,
  172. "sqwebmail: Cache create failure - who am I?");
  173. exit(1);
  174. }
  175. }
  176. userid=buf;
  177. if ((login_time=strchr(userid, ' ')) == 0)
  178. {
  179. syslog(LOG_DAEMON | LOG_CRIT,
  180. "sqwebmail: Cache create failure - bad code.");
  181. exit(1);
  182. }
  183. *login_time++=0;
  184. if ((data=strchr(login_time, ' ')) == 0)
  185. {
  186. syslog(LOG_DAEMON | LOG_CRIT,
  187. "sqwebmail: Cache create failure - bad code.");
  188. exit(1);
  189. }
  190. *data++=0;
  191. login_time_n=0;
  192. while (*login_time >= '0' && *login_time <= '9')
  193. login_time_n = login_time_n * 10 + (*login_time++ -'0');
  194. f=create_cache_name(userid, login_time_n);
  195. if ((fp=fopen(f, "w")) == 0) /* Try creating subdirs */
  196. {
  197. char *p=f+sizeof(CACHEDIR)-1;
  198. while (p && *p == '/')
  199. {
  200. *p=0;
  201. mkdir(f, 0700);
  202. *p='/';
  203. p=strchr(p+1, '/');
  204. }
  205. if ((fp=fopen(f, "w")) == 0)
  206. {
  207. syslog(LOG_DAEMON | LOG_CRIT,
  208. "sqwebmail: Cache create failure - file open.");
  209. exit(1);
  210. }
  211. }
  212. free(f);
  213. if ( fwrite(data, strlen(data), 1, fp) != 1)
  214. {
  215. fclose(fp);
  216. unlink(f); /* Problems */
  217. syslog(LOG_DAEMON | LOG_CRIT,
  218. "sqwebmail: Cache create failure - write error.");
  219. exit(1);
  220. }
  221. else fclose(fp);
  222. exit(0);
  223. }
  224. static int savebuf(char *p, int l)
  225. {
  226. while (l)
  227. {
  228. int n=write(childpipe, p, l);
  229. if (n <= 0) return (-1);
  230. p += n;
  231. l -= n;
  232. }
  233. return (0);
  234. }
  235. void save_login_cache(const char *a, time_t b)
  236. {
  237. char buf[1024];
  238. char buf2[NUMBUFSIZE];
  239. pid_t p;
  240. int waitstat;
  241. strcat(strcpy(buf, a), " ");
  242. strcat(strcat(buf, str_time_t(b, buf2)), " ");
  243. strcat(strcat(buf, str_uid_t(geteuid(), buf2)), " ");
  244. strcat(strcat(buf, str_gid_t(getegid(), buf2)), " ");
  245. buf[sizeof(buf)-1]=0;
  246. if (getcwd(buf+strlen(buf), sizeof(buf)-2-strlen(buf)) == 0)
  247. return; /* Oops */
  248. strcat(buf, "n");
  249. if (savebuf(buf, strlen(buf)) == 0)
  250. {
  251. int i;
  252. for (i=0; authvars[i]; i++)
  253. {
  254. const char *p;
  255. strcat(strcpy(buf, authvars[i]), "=");
  256. p=getenv(authvars[i]);
  257. if (!p || strlen(p)+strlen(buf) >= sizeof(buf)-2 ||
  258. strchr(p, 'n'))
  259. continue;
  260. strcat(strcat(buf, p), "n");
  261. if (savebuf(buf, strlen(buf))) break;
  262. }
  263. }
  264. close(childpipe);
  265. while ((p=wait(&waitstat)) != -1 && p != childproc)
  266. ;
  267. childproc= -1;
  268. }
  269. void cancel_login_cache()
  270. {
  271. if (childproc > 0)
  272. {
  273. kill(childproc, SIGTERM);
  274. close(childpipe);
  275. }
  276. }
  277. int check_login_cache(const char *a, time_t b)
  278. {
  279. char *f=create_cache_name(a, b);
  280. FILE *fp=fopen(f, "r");
  281. uid_t u;
  282. gid_t g;
  283. char dir[1024];
  284. int n;
  285. int c;
  286. static char *authbufs[ sizeof(authvars)/sizeof(authvars[0]) ]={0};
  287. free(f);
  288. if (!fp)
  289. return (-1);
  290. u=0;
  291. while ((c=getc(fp)) != ' ')
  292. {
  293. if (c < '0' || c > '9')
  294. {
  295. fclose(fp);
  296. return (-1);
  297. }
  298. u=u*10 + (c-'0');
  299. }
  300. g=0;
  301. while ((c=getc(fp)) != ' ')
  302. {
  303. if (c < '0' || c > '9')
  304. {
  305. fclose(fp);
  306. return (-1);
  307. }
  308. g=g*10 + (c-'0');
  309. }
  310. for (n=0; (c=getc(fp)) != EOF; n++)
  311. {
  312. if (c == 'n') break;
  313. if (n >= sizeof(dir)-1)
  314. {
  315. fclose(fp);
  316. syslog(LOG_DAEMON | LOG_CRIT,
  317. "sqwebmail: Cache create failure - bad cache.");
  318. fclose(fp);
  319. return (-1);
  320. }
  321. dir[n]=(char)c;
  322. }
  323. dir[n]=0;
  324. if (chdir(dir))
  325. {
  326. syslog(LOG_DAEMON | LOG_CRIT,
  327. "sqwebmail: Cache - can't chdir.");
  328. return (-1);
  329. }
  330. n=0;
  331. if (c != EOF)
  332. {
  333. while (fgets(dir, sizeof(dir), fp))
  334. {
  335. char *q;
  336. if ( (q=strchr(dir, 'n')) == 0)
  337. {
  338. fclose(fp);
  339. syslog(LOG_DAEMON | LOG_CRIT,
  340. "sqwebmail: Cache read failure - overflow.");
  341. return (-1);
  342. }
  343. *q=0;
  344. if (n >= sizeof(authbufs)/sizeof(authbufs[0]))
  345. {
  346. fclose(fp);
  347. return (-1);
  348. }
  349. if (authbufs[n]) free(authbufs[n]);
  350. authbufs[n]=malloc(strlen(dir)+1);
  351. if (!authbufs[n])
  352. {
  353. fclose(fp);
  354. return (-1);
  355. }
  356. strcpy(authbufs[n], dir);
  357. putenv(authbufs[n]);
  358. ++n;
  359. }
  360. fclose(fp);
  361. }
  362. if (setgid(g) || setuid(u))
  363. {
  364. return (-1);
  365. }
  366. return (0);
  367. }
  368. #endif