logincache.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:7k
- /*
- ** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
- ** distribution information.
- */
- #include "config.h"
- #include "logincache.h"
- #include "numlib/numlib.h"
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <pwd.h>
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <sys/types.h>
- #if HAVE_SYS_STAT_H
- #include <sys/stat.h>
- #endif
- #if HAVE_SYS_WAIT_H
- #include <sys/wait.h>
- #endif
- #if HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #if HAVE_SYSLOG_H
- #include <syslog.h>
- #else
- #define syslog(a,b)
- #endif
- #include "sqwebmail.h"
- static const char rcsid[]="$Id: logincache.c,v 1.9 2000/03/16 05:16:50 mrsam Exp $";
- #ifndef CACHEDIR
- /* Disabled */
- void init_login_cache(time_t a)
- {
- a=a;
- }
- void prepare_login_cache()
- {
- }
- void save_login_cache(const char *a, time_t b)
- {
- a=a;
- b=b;
- }
- void cancel_login_cache()
- {
- }
- int check_login_cache(const char *a, time_t b)
- {
- a=a;
- b=b;
- return (-1);
- }
- #else
- /* Need to cache the following environment variables */
- static const char * const authvars[] = { "AUTHADDR", "AUTHFULLNAME", 0 };
- static time_t expinterval;
- void init_login_cache(time_t n)
- {
- expinterval=n;
- }
- char *create_cache_name(const char *userid, time_t login_time)
- {
- int l;
- char buf[NUMBUFSIZE];
- const char *p;
- char *q;
- char *f, *g;
- login_time /= expinterval;
- l=1;
- for (p=userid; *p; p++)
- {
- ++l;
- if (*p == '/' || *p == '+' || *p < ' ' || *p >= 127)
- p += 2;
- }
- g=malloc(l);
- if (!g)
- {
- perror("malloc");
- enomem();
- }
- q=g;
- while (*userid)
- {
- if (*userid == '/' || *userid == '+' || *userid < ' '
- || *userid >= 127)
- {
- static char xdigit[]="0123456789ABCDEF";
- *q++ = '+';
- *q++ = xdigit[ (*userid >> 4) & 15 ];
- *q++ = xdigit[ (*userid) & 15 ];
- }
- else
- *q++ = *userid;
- ++userid;
- }
- *q=0;
- l=sizeof(CACHEDIR "//xx/");
- l += strlen(str_time_t( login_time, buf)) + strlen(g);
- f=malloc(l);
- if (!f)
- {
- perror("malloc");
- enomem();
- }
- strcat(strcat(strcpy(f, CACHEDIR "/"), buf), "/");
- strncpy(buf, g, 2);
- buf[2]=0;
- while (strlen(buf) < 2) strcat(buf, "+");
- strcat(strcat(strcat(f, buf), "/"), g);
- free(g);
- return (f);
- }
- static pid_t childproc= -1;
- static int childpipe;
- void prepare_login_cache()
- {
- int pipefd[2];
- char buf[2048];
- int i, j;
- char *userid, *login_time, *data;
- time_t login_time_n;
- char *f;
- FILE *fp;
- if (pipe(pipefd) < 0)
- {
- perror("pipe");
- enomem();
- }
- while ((childproc=fork()) < 0)
- {
- sleep(5);
- }
- if (childproc)
- {
- close(pipefd[0]);
- childpipe=pipefd[1];
- return;
- }
- close(pipefd[1]);
- i=0;
- for (;;)
- {
- if (i >= sizeof(buf)-1)
- {
- close(pipefd[0]);
- /* Problems */
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Max cache buffer overflow.");
- return;
- }
- j=read(pipefd[0], buf+i, sizeof(buf)-1-i);
- if (j < 0)
- {
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache create failure.");
- exit(1);
- }
- if (j == 0) break;
- i += j;
- }
- close(pipefd[0]);
- buf[i]=0;
- {
- struct passwd *pwd=getpwnam(CACHEOWNER);
- if (!pwd || setgid(pwd->pw_gid) || setuid(pwd->pw_uid))
- {
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache create failure - who am I?");
- exit(1);
- }
- }
- userid=buf;
- if ((login_time=strchr(userid, ' ')) == 0)
- {
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache create failure - bad code.");
- exit(1);
- }
- *login_time++=0;
- if ((data=strchr(login_time, ' ')) == 0)
- {
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache create failure - bad code.");
- exit(1);
- }
- *data++=0;
- login_time_n=0;
- while (*login_time >= '0' && *login_time <= '9')
- login_time_n = login_time_n * 10 + (*login_time++ -'0');
- f=create_cache_name(userid, login_time_n);
- if ((fp=fopen(f, "w")) == 0) /* Try creating subdirs */
- {
- char *p=f+sizeof(CACHEDIR)-1;
- while (p && *p == '/')
- {
- *p=0;
- mkdir(f, 0700);
- *p='/';
- p=strchr(p+1, '/');
- }
- if ((fp=fopen(f, "w")) == 0)
- {
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache create failure - file open.");
- exit(1);
- }
- }
- free(f);
- if ( fwrite(data, strlen(data), 1, fp) != 1)
- {
- fclose(fp);
- unlink(f); /* Problems */
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache create failure - write error.");
- exit(1);
- }
- else fclose(fp);
- exit(0);
- }
- static int savebuf(char *p, int l)
- {
- while (l)
- {
- int n=write(childpipe, p, l);
- if (n <= 0) return (-1);
- p += n;
- l -= n;
- }
- return (0);
- }
- void save_login_cache(const char *a, time_t b)
- {
- char buf[1024];
- char buf2[NUMBUFSIZE];
- pid_t p;
- int waitstat;
- strcat(strcpy(buf, a), " ");
- strcat(strcat(buf, str_time_t(b, buf2)), " ");
- strcat(strcat(buf, str_uid_t(geteuid(), buf2)), " ");
- strcat(strcat(buf, str_gid_t(getegid(), buf2)), " ");
- buf[sizeof(buf)-1]=0;
- if (getcwd(buf+strlen(buf), sizeof(buf)-2-strlen(buf)) == 0)
- return; /* Oops */
- strcat(buf, "n");
- if (savebuf(buf, strlen(buf)) == 0)
- {
- int i;
- for (i=0; authvars[i]; i++)
- {
- const char *p;
- strcat(strcpy(buf, authvars[i]), "=");
- p=getenv(authvars[i]);
- if (!p || strlen(p)+strlen(buf) >= sizeof(buf)-2 ||
- strchr(p, 'n'))
- continue;
- strcat(strcat(buf, p), "n");
- if (savebuf(buf, strlen(buf))) break;
- }
- }
- close(childpipe);
- while ((p=wait(&waitstat)) != -1 && p != childproc)
- ;
- childproc= -1;
- }
- void cancel_login_cache()
- {
- if (childproc > 0)
- {
- kill(childproc, SIGTERM);
- close(childpipe);
- }
- }
- int check_login_cache(const char *a, time_t b)
- {
- char *f=create_cache_name(a, b);
- FILE *fp=fopen(f, "r");
- uid_t u;
- gid_t g;
- char dir[1024];
- int n;
- int c;
- static char *authbufs[ sizeof(authvars)/sizeof(authvars[0]) ]={0};
- free(f);
- if (!fp)
- return (-1);
- u=0;
- while ((c=getc(fp)) != ' ')
- {
- if (c < '0' || c > '9')
- {
- fclose(fp);
- return (-1);
- }
- u=u*10 + (c-'0');
- }
- g=0;
- while ((c=getc(fp)) != ' ')
- {
- if (c < '0' || c > '9')
- {
- fclose(fp);
- return (-1);
- }
- g=g*10 + (c-'0');
- }
- for (n=0; (c=getc(fp)) != EOF; n++)
- {
- if (c == 'n') break;
- if (n >= sizeof(dir)-1)
- {
- fclose(fp);
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache create failure - bad cache.");
- fclose(fp);
- return (-1);
- }
- dir[n]=(char)c;
- }
- dir[n]=0;
- if (chdir(dir))
- {
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache - can't chdir.");
- return (-1);
- }
- n=0;
- if (c != EOF)
- {
- while (fgets(dir, sizeof(dir), fp))
- {
- char *q;
- if ( (q=strchr(dir, 'n')) == 0)
- {
- fclose(fp);
- syslog(LOG_DAEMON | LOG_CRIT,
- "sqwebmail: Cache read failure - overflow.");
- return (-1);
- }
- *q=0;
- if (n >= sizeof(authbufs)/sizeof(authbufs[0]))
- {
- fclose(fp);
- return (-1);
- }
- if (authbufs[n]) free(authbufs[n]);
- authbufs[n]=malloc(strlen(dir)+1);
- if (!authbufs[n])
- {
- fclose(fp);
- return (-1);
- }
- strcpy(authbufs[n], dir);
- putenv(authbufs[n]);
- ++n;
- }
- fclose(fp);
- }
- if (setgid(g) || setuid(u))
- {
- return (-1);
- }
- return (0);
- }
- #endif