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 + -
显示快捷键?