⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpd.c

📁 wu-ftpd类unix下的ftp服务器,可用于嵌入式系统
💻 C
📖 第 1 页 / 共 5 页
字号:
#else	setspent();	if ((spw = getspnam(p->pw_name)) != NULL) {#endif	    int expired = 0;	    /*XXX Does this work on all Shadow Password Implementations? */	    /* it is supposed to work on Solaris 2.x */	    time_t now;	    long today;	    now = time((time_t *) 0);	    today = now / (60 * 60 * 24);	    if ((spw->sp_expire > 0) && (spw->sp_expire < today))		expired++;	    if ((spw->sp_max > 0) && (spw->sp_lstchg > 0) &&		(spw->sp_lstchg + spw->sp_max < today))		expired++;	    free(save.pw_passwd);	    save.pw_passwd = sgetsave(expired ? "" : spw->sp_pwdp);	}/* Don't overwrite the password if the shadow read fails, getpwnam() is NIS   aware but getspnam() is not. *//* Shadow passwords are optional on Linux.  --marekm */#if !defined(LINUX) && !defined(UNIXWARE)	else {	    free(save.pw_passwd);	    save.pw_passwd = sgetsave("");	}#endif/* marekm's fix for linux proc file system shadow passwd exposure problem */#ifndef OTHER_PASSWD	endspent();#endif    }#endif    save.pw_gecos = sgetsave(p->pw_gecos);    save.pw_dir = sgetsave(p->pw_dir);    save.pw_shell = sgetsave(p->pw_shell);#ifdef M_UNIX    ret = &save;  DONE:    endpwent();#endif#if defined(SecureWare) || defined(HPUX_10_TRUSTED)    endprpwent();#endif#ifdef M_UNIX    return (ret);#else    return (&save);#endif}#if defined(SKEY) && !defined(__NetBSD__)/* * From Wietse Venema, Eindhoven University of Technology.  *//* skey_challenge - additional password prompt stuff */char *skey_challenge(char *name, struct passwd *pwd, int pwok){    static char buf[128];    char sbuf[40];    struct skey skey;    /* Display s/key challenge where appropriate. */    if (pwd == NULL || skeychallenge(&skey, pwd->pw_name, sbuf))	sprintf(buf, "Password required for %s.", name);    else	sprintf(buf, "%s %s for %s.", sbuf,		pwok ? "allowed" : "required", name);    return (buf);}#endifint login_attempts;		/* number of failed login attempts */int askpasswd;			/* had user command, ask for passwd */#ifndef HELP_CRACKERSint DenyLoginAfterPassword;char DelayedMessageFile[MAXPATHLEN];extern void pr_mesg(int msgcode, char *msgfile);#endif#if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)static int defaultserver_allow(const char *username){    struct aclmember *entry = NULL;    int which;    while (getaclentry("defaultserver", &entry))	if (ARG0 && !strcasecmp(ARG0, "allow"))	    for (which = 1; (which < MAXARGS) && ARG[which]; which++)		if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which]))		    return (1);    return (0);}static int defaultserver_deny(const char *username){    struct aclmember *entry = NULL;    int which;    while (getaclentry("defaultserver", &entry))	if (ARG0 && !strcasecmp(ARG0, "deny"))	    for (which = 1; (which < MAXARGS) && ARG[which]; which++)		if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which]))		    return (1);    return (0);}static int defaultserver_private(void){    struct aclmember *entry = NULL;    while (getaclentry("defaultserver", &entry))	if (ARG0 && !strcasecmp(ARG0, "private"))	    return (1);    return (0);}#endif/* USER command. Sets global passwd pointer pw if named account exists and is * acceptable; sets askpasswd if a PASS command is expected.  If logged in * previously, need to reset state.  If name is "ftp" or "anonymous", the * name is not in _PATH_FTPUSERS, and ftp account exists, set anonymous and * pw, then just return.  If account doesn't exist, ask for passwd anyway. * Otherwise, check user requesting login privileges.  Disallow anyone who * does not have a standard shell as returned by getusershell().  Disallow * anyone mentioned in the file _PATH_FTPUSERS to allow people such as root * and uucp to be avoided. *//*   char *getusershell(); */void user(char *name){    char *cp;    char *shell;#ifdef	BSD_AUTH    char *auth;#endif/* H* fix: if we're logged in at all, we can't log in again. */    if (logged_in) {#ifdef VERBOSE_ERROR_LOGING	syslog(LOG_NOTICE, "FTP LOGIN REFUSED (already logged in as %s) FROM %s, %s",	       pw->pw_name, remoteident, name);#endif	reply(530, "Already logged in.");	return;    }#ifndef HELP_CRACKERS    askpasswd = 1;    DenyLoginAfterPassword = 0;    DelayedMessageFile[0] = '\0';#endif#ifdef	BSD_AUTH    if ((auth = strchr(name, ':')))	*auth++ = 0;#endif#ifdef HOST_ACCESS		/* 19-Mar-93    BM              */    if (!rhost_ok(name, remotehost, remoteaddr)) {#ifndef HELP_CRACKERS	DenyLoginAfterPassword = 1;	syslog(LOG_NOTICE, "FTP LOGIN REFUSED (name in %s) FROM %s, %s",	       _PATH_FTPHOSTS, remoteident, name);#else	reply(530, "User %s access denied.", name);	syslog(LOG_NOTICE,	       "FTP LOGIN REFUSED (name in %s) FROM %s, %s",	       _PATH_FTPHOSTS, remoteident, name);	return;#endif    }#endif#ifdef LOG_FAILED		/* 06-Nov-92    EHK             */    strncpy(the_user, name, MAXUSERNAMELEN - 1);#endif    anonymous = 0;    acl_remove();    if (!strcasecmp(name, "ftp") || !strcasecmp(name, "anonymous")) {	struct aclmember *entry = NULL;	int machineok = 1;	char guestservername[MAXHOSTNAMELEN];	guestservername[0] = '\0';#ifdef NO_ANONYMOUS_ACCESS	reply(530, "Anonymous FTP access denied.");	syslog(LOG_NOTICE, "FTP LOGIN REFUSED (anonymous ftp not supported) FROM %s, %s",	       remoteident, name);	return;#else#if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)	if (!virtual_mode && defaultserver_private()) {#ifndef HELP_CRACKERS	    DenyLoginAfterPassword = 1;	    syslog(LOG_NOTICE, "FTP LOGIN REFUSED (anonymous ftp denied on default server) FROM %s, %s",		   remoteident, name);#else	    reply(530, "User %s access denied.", name);	    syslog(LOG_NOTICE,		   "FTP LOGIN REFUSED (anonymous ftp denied on default server) FROM %s, %s",		   remoteident, name);	    return;#endif	}#endif	if (checkuser("ftp") || checkuser("anonymous")) {#ifndef HELP_CRACKERS	    DenyLoginAfterPassword = 1;	    syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp in %s) FROM %s, %s",		   _PATH_FTPUSERS, remoteident, name);#else	    reply(530, "User %s access denied.", name);	    syslog(LOG_NOTICE,		   "FTP LOGIN REFUSED (ftp in %s) FROM %s, %s",		   _PATH_FTPUSERS, remoteident, name);	    return;#endif	    /*	       ** Algorithm used:	       ** - if no "guestserver" directive is present,	       **     anonymous access is allowed, for backward compatibility.	       ** - if a "guestserver" directive is present,	       **     anonymous access is restricted to the machines listed,	       **     usually the machine whose CNAME on the current domain	       **     is "ftp"...	       **	       ** the format of the "guestserver" line is	       ** guestserver [<machine1> [<machineN>]]	       ** that is, "guestserver" will forbid anonymous access on all machines	       ** while "guestserver ftp inf" will allow anonymous access on	       ** the two machines whose CNAMES are "ftp.enst.fr" and "inf.enst.fr".	       **	       ** if anonymous access is denied on the current machine,	       ** the user will be asked to use the first machine listed (if any)	       ** on the "guestserver" line instead:	       ** 530- Guest login not allowed on this machine,	       **      connect to ftp.enst.fr instead.	       **	       ** -- <Nicolas.Pioch@enst.fr>	     */	}	else if (getaclentry("guestserver", &entry)		 && ARG0 && (int) strlen(ARG0) > 0) {	    struct hostent *tmphostent;	    /*	       ** if a "guestserver" line is present,	       ** default is not to allow guest logins	     */	    machineok = 0;	    if (hostname[0]		&& ((tmphostent = gethostbyname(hostname)))) {		/*		   ** hostname is the only first part of the FQDN		   ** this may or may not correspond to the h_name value		   ** (machines with more than one IP#, CNAMEs...)		   ** -> need to fix that, calling gethostbyname on hostname		   **		   ** WARNING!		   ** for SunOS 4.x, you need to have a working resolver in the libc		   ** for CNAMES to work properly.		   ** If you don't, add "-lresolv" to the libraries before compiling!		 */		char dns_localhost[MAXHOSTNAMELEN];		int machinecount;		strncpy(dns_localhost,			tmphostent->h_name,			sizeof(dns_localhost));		dns_localhost[sizeof(dns_localhost) - 1] = '\0';		for (machinecount = 0;		  entry->arg[machinecount] && (entry->arg[machinecount])[0];		     machinecount++) {		    if ((tmphostent = gethostbyname(entry->arg[machinecount]))) {			/*			   ** remember the name of the first machine for redirection			 */			if ((!machinecount) && tmphostent->h_name) {			    strncpy(guestservername, entry->arg[machinecount],				    sizeof(guestservername));			    guestservername[sizeof(guestservername) - 1] = '\0';			}			if (!strcasecmp(tmphostent->h_name, dns_localhost)) {			    machineok++;			    break;			}		    }		}	    }	}	if (!machineok) {	    if (guestservername[0])		reply(530,		      "Guest login not allowed on this machine, connect to %s instead.",		      guestservername);	    else		reply(530,		      "Guest login not allowed on this machine.");	    syslog(LOG_NOTICE,	    "FTP LOGIN REFUSED (localhost not in guestservers) FROM %s, %s",		   remoteident, name);	    /* End of the big patch -- Nap */	}	else if ((pw = sgetpwnam("ftp")) != NULL) {	    anonymous = 1;	/* for the access_ok call */	    if (access_ok(530) < 1) {#ifndef HELP_CRACKERS		DenyLoginAfterPassword = 1;		syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s",		       remoteident, name);		reply(331, "Guest login ok, send your complete e-mail address as password.");#else		reply(530, "User %s access denied.", name);		syslog(LOG_NOTICE,		       "FTP LOGIN REFUSED (access denied) FROM %s, %s",		       remoteident, name);		dologout(0);#endif	    }	    else {		askpasswd = 1;/* H* fix: obey use_accessfile a little better.  This way, things set on the   command line [like xferlog stuff] don't get stupidly overridden.   XXX: all these checks maybe should be in acl.c and access.c */		if (use_accessfile)		    acl_setfunctions();		reply(331, "Guest login ok, send your complete e-mail address as password.");	    }	}	else {#ifndef HELP_CRACKERS	    DenyLoginAfterPassword = 1;	    reply(331, "Guest login ok, send your complete e-mail address as password.");	    syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp not in /etc/passwd) FROM %s, %s",		   remoteident, name);#else	    reply(530, "User %s unknown.", name);	    syslog(LOG_NOTICE,		   "FTP LOGIN REFUSED (ftp not in /etc/passwd) FROM %s, %s",		   remoteident, name);#endif	}	return;#endif    }#ifdef ANON_ONLY/* H* fix: define the above to completely DISABLE logins by real users,   despite ftpusers, shells, or any of that rot.  You can always hang your   "real" server off some other port, and access-control it. */    else {			/* "ftp" or "anon" -- MARK your conditionals, okay?! */#ifndef HELP_CRACKERS	DenyLoginAfterPassword = 1;	syslog(LOG_NOTICE, "FTP LOGIN REFUSED (not anonymous) FROM %s, %s",	       remoteident, name);	reply(331, "Password required for %s.", name);#else	reply(530, "User %s unknown.", name);	syslog(LOG_NOTICE,	       "FTP LOGIN REFUSED (not anonymous) FROM %s, %s",	       remoteident, name);#endif	return;    }/* fall here if username okay in any case */#endif /* ANON_ONLY */#if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)    if (!virtual_mode && defaultserver_deny(name) && !defaultserver_allow(name)) {#ifndef HELP_CRACKERS	DenyLoginAfterPassword = 1;	syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp denied on default server) FROM %s, %s",	       remoteident, name);#else	reply(530, "User %s access denied.", name);	syslog(LOG_NOTICE,	     "FTP LOGIN REFUSED (ftp denied on default server) FROM %s, %s",	       remoteident, name);	return;#endif    }#endif    if ((pw = sgetpwnam(name)) != NULL) {	if ((denieduid(pw->pw_uid) && !alloweduid(pw->pw_uid))	    || (deniedgid(pw->pw_gid) && !allowedgid(pw->pw_gid))) {#ifndef HELP_CRACKERS	    DenyLoginAfterPassword = 1;	    syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in denied-uid) FROM %s, %s",		   remoteident, name);	    reply(331, "Password required for %s.", name);#else	    reply(530, "User %s access denied.", name);	    syslog(LOG_NOTICE,		   "FTP LOGIN REFUSED (username in denied-uid) FROM %s, %s",		   remoteident, name);#endif	    return;	}#if !defined(USE_PAM) || (defined(USE_PAM) && defined(OTHER_PASSWD))	/* PAM should be doing these checks, not ftpd */#ifdef USE_PAM	if(!use_pam) {#endif	if ((shell = pw->pw_shell) == NULL || *shell == 0)	    shell = _PATH_BSHELL;	while ((cp = getusershell()) != NULL)	    if (strcmp(cp, shell) == 0)		break;	endusershell();	if (cp == NULL || checkuser(name)) {#ifndef HELP_CRACKERS	    DenyLoginAfterPassword = 1;	    if (cp == NULL)		syslog(LOG_NOTICE, "FTP LOGIN REFUSED (shell not in /etc/shells) FROM %s, %s", remoteident, name);	    else		syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in %s) FROM %s, %s", _PATH_FTPUSERS, remoteident, name);	    reply(331, "Password required for %s.", name);#else	    reply(530, "User %s access denied.", name);	    if (cp == NULL)		syslog(LOG_NOTICE, "FTP LOGIN REFUSED (shell not in /etc/shells) FROM %s, %s", remoteident, name);	    else		syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in %s) FROM %s, %s", _PATH_FTPUSERS, remoteident, name);#endif /* HELP_CRACKERS */	    pw = (struct passwd *) NULL;	    return;	}#ifdef USE_PAM	} /* if(!use_pam) */#endif#endif /* !USE_PAM || (USE_PAM && OTHER_PASSWD) */	/* if user is a member of any of the guestgroups, cause a chroot() */	/* after they log in successfully                                  */	if (use_accessfile) {	/* see above.  _H */	    guest = acl_guestgroup(pw);	    if (guest && acl_realgroup(pw))		guest = 0;	}    }    if (access_ok(530) < 1) {#ifndef HELP_CRACKERS	DenyLoginAfterPassword = 1;	syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s",	       remoteident, name);	reply(331, "Password required for %s.", name);#else	reply(530, "User %s access denied.", name);	syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s",	       remoteident, name);#endif	return;    }    else if (use_accessfile)	/* see above.  _H */	acl_setfunctions();#ifdef	BSD_AUTH    if ((cp = start_auth(auth, name, pw)) != NULL) {	char *s;	for (;;) {	    s = strsep(&cp, "\n");	    if (cp == NULL || *cp == '\0')		break;	    lreply(331, "%s", s);	}	reply(331, "%s", s);    }    else {#endif#ifdef SKEY#ifndef __NetBSD__#ifdef SKEY_NAME	/* this is the old way, but freebsd uses it */	pwok = skeyaccess(name, NULL, remotehost, remoteaddr);#else	/* this is the new way */	pwok = skeyaccess(pw, NULL, remotehost, remoteaddr);#endif	reply(331, "%s", skey_challenge(name, pw, pwok));#else	if (skey_haskey(name) == 0) {	    char *myskey;	    myskey = skey_keyinfo(name);	    reply(331, "Password [%s] required for %s.",		  myskey ? myskey : "error getting challenge", name);	}	else	    reply(331, "Password required for %s.", name);#endif#else#ifdef OPIE	{	    char prompt[OPIE_CHALLENGE_MAX + 1];	    opiechallenge(&opiestate, name, prompt);	    if (askpasswd == -1) {		syslog(LOG_WARNING, "Invalid FTP user name %s attempted from %s", name, remotehost);		pwok = 0;	    }	    else		pwok = af_pwok && opiealways(pw->pw_dir);	    reply(331, "Response to %s %s for %s.",		  prompt, pwok ? "requested" : "required", name);	}#else	reply(331, "Password required for %s.", name);#endif#endif#ifdef	BSD_AUTH    }#endif    askpasswd = 1;    /* Delay before reading passwd after first failed attempt to slow down     * passwd-guessing programs. */

⌨️ 快捷键说明

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