env_unix.c

来自「这是用C编写IMAP源代码」· C语言 代码 · 共 1,641 行 · 第 1/4 页

C
1,641
字号
/* Write current time in internal format * Accepts: destination string */void internal_date (char *date){  do_date (date,NIL,"%02d-%s-%d %02d:%02d:%02d %+03d%02d",NIL);}/* Initialize server * Accepts: server name for syslog or NIL *	    /etc/services service name or NIL *	    alternate /etc/services service name or NIL *	    clock interrupt handler *	    kiss-of-death interrupt handler *	    hangup interrupt handler *	    termination interrupt handler */void server_init (char *server,char *service,char *sslservice,		  void *clkint,void *kodint,void *hupint,void *trmint){				/* only do this if for init call */  if (server && service && sslservice) {    int mask;    long port;    struct servent *sv;				/* set server name in syslog */    openlog (server,LOG_PID,LOG_MAIL);    fclose (stderr);		/* possibly save a process ID */    dorc (NIL,NIL);		/* do systemwide configuration */    /* Use SSL if SSL service, or if server starts with "s" and not service */    if (((port = tcp_serverport ()) >= 0)) {      if ((sv = getservbyname (service,"tcp")) && (port == ntohs (sv->s_port)))	syslog (LOG_DEBUG,"%s service init from %s",service,tcp_clientaddr ());      else if ((sv = getservbyname (sslservice,"tcp")) &&	       (port == ntohs (sv->s_port))) {	syslog (LOG_DEBUG,"%s SSL service init from %s",sslservice,		tcp_clientaddr ());	ssl_server_init (server);      }      else {			/* not service or SSL service port */	syslog (LOG_DEBUG,"port %ld service init from %s",port,		tcp_clientaddr ());	if (*server == 's') ssl_server_init (server);      }    }    switch (mask = umask (022)){/* check old umask */    case 0:			/* definitely unreasonable */    case 022:			/* don't need to change it */      break;    default:			/* already was a reasonable value */      umask (mask);		/* so change it back */    }  }  arm_signal (SIGALRM,clkint);	/* prepare for clock interrupt */  arm_signal (SIGUSR2,kodint);	/* prepare for Kiss Of Death */  arm_signal (SIGHUP,hupint);	/* prepare for hangup */  arm_signal (SIGTERM,trmint);	/* prepare for termination */}/* Wait for stdin input * Accepts: timeout in seconds * Returns: T if have input on stdin, else NIL */long server_input_wait (long seconds){  fd_set rfd,efd;  struct timeval tmo;  FD_ZERO (&rfd);  FD_ZERO (&efd);  FD_SET (0,&rfd);  FD_SET (0,&efd);  tmo.tv_sec = seconds; tmo.tv_usec = 0;  return select (1,&rfd,0,&efd,&tmo) ? LONGT : NIL;}/* Return UNIX password entry for user name * Accepts: user name string * Returns: password entry * * Tries all-lowercase form of user name if given user name fails */static struct passwd *pwuser (unsigned char *user){  unsigned char *s;  struct passwd *pw = getpwnam (user);  if (!pw) {			/* failed, see if any uppercase characters */    for (s = user; *s && !isupper (*s); s++);    if (*s) {			/* yes, try all lowercase form */      pw = getpwnam (s = lcase (cpystr (user)));      fs_give ((void **) &s);    }  }  return pw;}/* Validate password for user name * Accepts: user name string *	    password string *	    argument count *	    argument vector * Returns: password entry if validated * * Tries password+1 if password fails and starts with space */static struct passwd *valpwd (char *user,char *pwd,int argc,char *argv[]){  char *s;  struct passwd *pw;  struct passwd *ret = NIL;  if (auth_md5.server) {	/* using CRAM-MD5 authentication? */    if (s = auth_md5_pwd (user)) {      if (!strcmp (s,pwd) || ((*pwd == ' ') && pwd[1] && !strcmp (s,pwd+1)))	ret = pwuser (user);	/* validated, get passwd entry for user */      memset (s,0,strlen (s));	/* erase sensitive information */      fs_give ((void **) &s);    }  }  else if (pw = pwuser (user)) {/* can get user? */    s = cpystr (pw->pw_name);	/* copy returned name in case we need it */    if (*pwd && !(ret = checkpw (pw,pwd,argc,argv)) &&	(*pwd == ' ') && pwd[1] && (ret = pwuser (s)))      ret = checkpw (pw,pwd+1,argc,argv);    fs_give ((void **) &s);	/* don't need copy of name any more */  }  return ret;}/* Server log in * Accepts: user name string *	    password string *	    authenticating user name string *	    argument count *	    argument vector * Returns: T if password validated, NIL otherwise */long server_login (char *user,char *pwd,char *authuser,int argc,char *argv[]){  struct passwd *pw = NIL;  int level = LOG_NOTICE;  char *err = "failed";				/* cretins still haven't given up */  if ((strlen (user) >= NETMAXUSER) ||      (authuser && (strlen (authuser) >= NETMAXUSER))) {    level = LOG_ALERT;		/* escalate this alert */    err = "SYSTEM BREAK-IN ATTEMPT";    logtry = 0;			/* render this session useless */  }  else if (logtry-- <= 0) err = "excessive login failures";  else if (disablePlaintext) err = "disabled";  else if (!(authuser && *authuser)) pw = valpwd (user,pwd,argc,argv);  else if (valpwd (authuser,pwd,argc,argv)) pw = pwuser (user);  if (pw && pw_login (pw,authuser,pw->pw_name,NIL,argc,argv)) return T;  syslog (level|LOG_AUTH,"Login %s user=%.64s auth=%.64s host=%.80s",err,	  user,(authuser && *authuser) ? authuser : user,tcp_clienthost ());  sleep (3);			/* slow down possible cracker */  return NIL;}/* Authenticated server log in * Accepts: user name string *	    authenticating user name string *	    argument count *	    argument vector * Returns: T if password validated, NIL otherwise */long authserver_login (char *user,char *authuser,int argc,char *argv[]){  return pw_login (pwuser (user),authuser,user,NIL,argc,argv);}/* Log in as anonymous daemon * Accepts: argument count *	    argument vector * Returns: T if successful, NIL if error */long anonymous_login (int argc,char *argv[]){				/* log in Mr. A. N. Onymous */  return pw_login (getpwnam (ANONYMOUSUSER),NIL,NIL,		   (char *) mail_parameters (NIL,GET_ANONYMOUSHOME,NIL),		   argc,argv);}/* Finish log in and environment initialization * Accepts: passwd struct for loginpw() *	    optional authentication user name *	    user name (NIL for anonymous) *	    home directory (NIL to use directory from passwd struct) *	    argument count *	    argument vector * Returns: T if successful, NIL if error */long pw_login (struct passwd *pw,char *auser,char *user,char *home,int argc,	       char *argv[]){  struct group *gr;  char **t;  long ret = NIL;  if (pw && pw->pw_uid) {	/* must have passwd struct for non-UID 0 */				/* make safe copies of user and home */    if (user) user = cpystr (pw->pw_name);    home = cpystr (home ? home : pw->pw_dir);				/* authorization ID .NE. authentication ID? */    if (user && auser && *auser && compare_cstring (auser,user)) {				/* scan list of mail administrators */      if ((gr = getgrnam (ADMINGROUP)) && (t = gr->gr_mem)) while (*t && !ret)	if (!compare_cstring (auser,*t++))	  ret = pw_login (pw,NIL,user,home,argc,argv);      syslog (LOG_NOTICE|LOG_AUTH,"%s %.80s override of user=%.80s host=%.80s",	      ret ? "Admin" : "Failed",auser,user,tcp_clienthost ());    }    else if (closedBox) {	/* paranoid site, lock out other directories */      if (chdir (home) || chroot (home))	syslog (LOG_NOTICE|LOG_AUTH,		"Login %s failed: unable to set chroot=%.80s host=%.80s",		pw->pw_name,home,tcp_clienthost ());      else if (loginpw (pw,argc,argv)) ret = env_init (user,NIL);      else fatal ("Login failed after chroot");    }				/* normal login */    else if (((pw->pw_uid == geteuid ()) || loginpw (pw,argc,argv)) &&	     (ret = env_init (user,home))) chdir (myhomedir ());    fs_give ((void **) &home);	/* clean up */    if (user) fs_give ((void **) &user);  }  endpwent ();			/* in case shadow passwords in pw data */  return ret;			/* return status */}/* Initialize environment * Accepts: user name (NIL for anonymous) *	    home directory name * Returns: T, always */long env_init (char *user,char *home){  extern MAILSTREAM CREATEPROTO;  extern MAILSTREAM EMPTYPROTO;  struct passwd *pw;  struct stat sbuf;  char tmp[MAILTMPLEN];  if (myUserName) fatal ("env_init called twice!");				/* initially nothing in namespace list */  nslist[0] = nslist[1] = nslist[2] = NIL;				/* myUserName must be set before dorc() call */  myUserName = cpystr (user ? user : ANONYMOUSUSER);  dorc (NIL,NIL);		/* do systemwide configuration */  if (!home) {			/* closed box server */				/* standard user can only reference home */    if (user) nslist[0] = &nshome;    else {			/* anonymous user */      nslist[0] = &nsblackother; /* set root */      anonymous = T;		/* flag as anonymous */    }    myHomeDir = cpystr ("");	/* home directory is root */    sysInbox = cpystr ("INBOX");/* make system INBOX */  }  else {			/* open or black box */    closedBox = NIL;		/* definitely not a closed box */    if (user) {			/* remember user name and home directory */      if (blackBoxDir) {	/* build black box directory name */	sprintf (tmp,"%s/%s",blackBoxDir,myUserName);				/* must exist */	if (!((!stat (home = tmp,&sbuf) && (sbuf.st_mode & S_IFDIR)) ||	      (blackBoxDefaultHome &&	       !stat (home = blackBoxDefaultHome,&sbuf) &&	       (sbuf.st_mode & S_IFDIR)))) fatal ("no home");	sysInbox = (char *) fs_get (strlen (home) + 7);				/* set system INBOX */	sprintf (sysInbox,"%s/INBOX",home);	blackBox = T;		/* mark that it's a black box */				/* mbox meaningless if black box */	mail_parameters (NIL,DISABLE_DRIVER,(void *) "mbox");      }      nslist[0] = &nshome;	/* home namespace */				/* limited advertise namespaces */      if (limitedadvertise) nslist[2] = &nslimited;      else if (blackBox) {	/* black box namespaces */	nslist[1] = &nsblackother;	nslist[2] = &nsshared;      }      else {			/* open box namespaces */	nslist[1] = &nsunixother;	nslist[2] = advertisetheworld ? &nsworld : &nsshared;      }    }    else {      nslist[2] = &nsftp;	/* anonymous user */      sprintf (tmp,"%s/INBOX",	       home = (char *) mail_parameters (NIL,GET_ANONYMOUSHOME,NIL));      sysInbox = cpystr (tmp);	/* make system INBOX */      anonymous = T;		/* flag as anonymous */    }    myHomeDir = cpystr (home);	/* set home directory */  }  if (allowuserconfig) {	/* allow user config files */    dorc (strcat (strcpy (tmp,myHomeDir),"/.mminit"),T);    dorc (strcat (strcpy (tmp,myHomeDir),"/.imaprc"),NIL);  }  if (!closedBox && !noautomaticsharedns) {				/* #ftp namespace */    if (!ftpHome && (pw = getpwnam ("ftp"))) ftpHome = cpystr (pw->pw_dir);				/* #public namespace */    if (!publicHome && (pw = getpwnam ("imappublic")))      publicHome = cpystr (pw->pw_dir);				/* #shared namespace */    if (!anonymous && !sharedHome && (pw = getpwnam ("imapshared")))      sharedHome = cpystr (pw->pw_dir);  }  if (!myLocalHost) mylocalhost ();  if (!myNewsrc) myNewsrc = cpystr(strcat (strcpy (tmp,myHomeDir),"/.newsrc"));  if (!newsActive) newsActive = cpystr (ACTIVEFILE);  if (!newsSpool) newsSpool = cpystr (NEWSSPOOL);				/* force default prototype to be set */  if (!createProto) createProto = &CREATEPROTO;  if (!appendProto) appendProto = &EMPTYPROTO;				/* re-do open action to get flags */  (*createProto->dtb->open) (NIL);  endpwent ();			/* close pw database */  return T;} /* Return my user name * Accepts: pointer to optional flags * Returns: my user name */char *myusername_full (unsigned long *flags){  struct passwd *pw;  struct stat sbuf;  char *s;  unsigned long euid;  char *ret = UNLOGGEDUSER;				/* no user name yet and not root? */  if (!myUserName && (euid = geteuid ())) {				/* yes, look up getlogin() user name or EUID */    if (((s = (char *) getlogin ()) && *s && (strlen (s) < NETMAXUSER) &&	 (pw = getpwnam (s)) && (pw->pw_uid == euid)) ||	(pw = getpwuid (euid)))      env_init (pw->pw_name,		((s = getenv ("HOME")) && *s && (strlen (s) < NETMAXMBX) &&		 !stat (s,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFDIR)) ?		s : pw->pw_dir);    else fatal ("Unable to look up user name");  }  if (myUserName) {		/* logged in? */    if (flags) *flags = anonymous ? MU_ANONYMOUS : MU_LOGGEDIN;    ret = myUserName;		/* return user name */  }  else if (flags) *flags = MU_NOTLOGGEDIN;  return ret;}/* Return my local host name * Returns: my local host name */char *mylocalhost (){  char tmp[MAILTMPLEN];  if (!myLocalHost) {    gethostname(tmp,MAILTMPLEN);/* get local host name */    myLocalHost = cpystr (tcp_canonical (tmp));  }  return myLocalHost;}/* Return my home directory name * Returns: my home directory name */char *myhomedir (){  if (!myHomeDir) myusername ();/* initialize if first time */  return myHomeDir ? myHomeDir : "";}/* Return my home mailbox name * Returns: my home directory name */static char *mymailboxdir (){  char *home = myhomedir ();				/* initialize if first time */  if (!myMailboxDir && myHomeDir) {    if (mailsubdir) {      char tmp[MAILTMPLEN];      sprintf (tmp,"%s/%s",home,mailsubdir);      myMailboxDir = cpystr (tmp);/* use pre-defined subdirectory of home */    }    else myMailboxDir = cpystr (home);  }  return myMailboxDir ? myMailboxDir : "";}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?