Example #1
0
int ftp_login(const char *guessed_username, const char *anonpass)
{
    int ptype, r;
    static url_t *purl = 0;

    if(!ftp_connected())
        return 1;

    if(!ftp->url)
        return -1;

#ifdef HAVE_LIBSSH
    if (ftp->session)
        /* login authentication is performed by the ssh program */
        return 0;
#endif

    ptype = proxy_type(ftp->url);
    if(purl) {
        url_destroy(purl);
        purl = 0;
    }
    if(ptype > 0)
        purl = url_clone(gvProxyUrl);

    r = get_username(ftp->url, guessed_username, false);
    if(r != 0)
        return r;
    if(ptype > 1 && ptype < 7) {
        r = get_username(purl, 0, true);
        if(r != 0)
            return r;
    }

#ifdef SECFTP
    ftp->sec_complete = false;
    ftp->data_prot = prot_clear;

    /* don't use secure stuff if anonymous
     */
    if(!url_isanon(ftp->url)) {
        list *mechlist;
        /* request a protection level
         */
        if(ftp->url->protlevel) {
            if(sec_request_prot(ftp->url->protlevel) != 0)
                ftp_err(_("Invalid protection level '%s'\n"),
                        ftp->url->protlevel);
        }

        /* get list of mechanisms to try
         */
        mechlist = ftp->url->mech ? ftp->url->mech : gvDefaultMechanism;
        if(mechlist) {
            listitem *li = mechlist->first;
            int ret = 0;
            for(; li; li=li->next) {
                const char *mech_name;

                mech_name = secext_name((char *)li->data);
                if(mech_name == 0) {
                    ftp_err(_("unknown mechanism '%s'\n"), (char *)li->data);
                    continue;
                }
                if(mech_unsupported(mech_name)) {
                    ftp_err(_("Yafc was not compiled with support for %s\n"),
                            mech_name);
                    continue;
                }
                ret = sec_login(host_getname(ftp->host), mech_name);
                if(ret == -1) {
                    if(ftp->code == ctError
                       && ftp->fullcode != 504 && ftp->fullcode != 534)
                        url_setmech(ftp->url, "none");
                }
                if(ret != 1)
                    break;
            }
        }
        if(ftp->sec_complete)
            ftp_err(_("Authentication successful.\n"));
        else
            ftp_err(_("*** Using plaintext username"
                      " and password ***\n"));
    }
#endif

    if(url_isanon(ftp->url))
        fprintf(stderr, _("logging in anonymously...\n"));
    ftp_set_tmp_verbosity(ftp->url->password ? vbError : vbCommand);

    switch(ptype) {
      case 0:
      default:
        ftp_cmd("USER %s", ftp->url->username);
        break;
      case 1:
        ftp_cmd("USER %s@%s", ftp->url->username, ftp->url->hostname);
        break;
      case 2:
      case 3:
      case 4:
        ftp_cmd("USER %s", purl->username);
        if(ftp->code == ctContinue) {
            r = get_password(purl, 0, true);
            if(r != 0)
                return 0;
            ftp_cmd("PASS %s", purl->password);
            /* FIXME: what reply code do we expect now? */
            if(ftp->code < ctTransient) {
                if(ptype == 2) {
                    ftp_cmd("USER %s@%s",
                            ftp->url->username, ftp->url->hostname);
                } else {
                    if(ptype == 3)
                        ftp_cmd("SITE %s", purl->hostname);
                    else
                        ftp_cmd("OPEN %s", purl->hostname);
                    if(ftp->code < ctTransient)
                        ftp_cmd("USER %s", ftp->url->username);
                }
            }
        }
        break;
      case 5:
        ftp_cmd("USER %s@%s@%s",
                ftp->url->username, purl->username, ftp->url->hostname);
        break;
      case 6:
        ftp_cmd("USER %s@%s", purl->username, ftp->url->hostname);
        if(ftp->code == ctContinue) {
            r = get_password(purl, 0, true);
            if(r != 0)
                return 0;
            ftp_cmd("PASS %s", purl->password);
            if(ftp->code < ctTransient)
                ftp_cmd("USER %s", ftp->url->username);
        }
        break;
      case 7:
        ftp_cmd("USER %s@%s:%i", ftp->url->username, ftp->url->hostname, ftp->url->port);
        break;
    }

    if(ftp->code == ctContinue) {
        ftp->loggedin = false;
        r = get_password(ftp->url, anonpass, false);
        if(r != 0)
            return r;
        if(ptype == 5) {
            r = get_password(purl, 0, true);
            if(r != 0) {
                url_destroy(purl);
                purl = 0;
                return 0;
            }
        }

        ftp_set_tmp_verbosity(vbCommand);
        switch(ptype) {
          default:
          case 0:
          case 1:
          case 2:
          case 3:
          case 4:
          case 6:
            ftp_cmd("PASS %s", ftp->url->password);
            break;
          case 5:
            ftp_cmd("PASS %s@%s", ftp->url->password, purl->password);
            break;

        }
    }

    url_destroy(purl);
    purl = 0;

    if(ftp->code > ctContinue) {
        if(ftp->fullcode == 530 && ftp_loggedin()) {
            /* this probable means '530 Already logged in' */
            return 2;
        }
        ftp->loggedin = false;
        return 1;
    }
    if(ftp->code == ctComplete) {
        ftp->loggedin = true;
#ifdef SECFTP
        /* we are logged in, now set the requested data protection level
         * requested from the autologin information in the config file,
         * if any, else uses default protection level 'clear', ie
         * no protection on the data channel
         */
        if(ftp->sec_complete) {
            sec_set_protection_level();
            fprintf(stderr, _("Data protection is %s\n"),
                    level_to_name(ftp->data_prot));
        }
#endif
        ftp->homedir = ftp_getcurdir();
        ftp->curdir = xstrdup(ftp->homedir);
        ftp->prevdir = xstrdup(ftp->homedir);
        if(ftp->url->directory)
            ftp_chdir(ftp->url->directory);
        ftp_get_feat();
        return 0;
    }
    if(ftp->code == ctTransient)
        return 1;
    return -1;
}
Example #2
0
int
ruserpassword(char *host, char **aname, char **apass, char **aacct)
{
    char *hdir, buf[BUFSIZ], *tmp;
    int t, i, c, usedefault = 0;
    struct stat stb;

    mydomain = guess_domain (myhostname, MaxHostNameLen);

    hdir = getenv("HOME");
    if (hdir == NULL)
	hdir = ".";
    snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
    cfile = fopen(buf, "r");
    if (cfile == NULL) {
	if (errno != ENOENT)
	    warn("%s", buf);
	return (0);
    }

next:
    while ((t = token())) switch(t) {

    case DEFAULT:
	usedefault = 1;
	/* FALL THROUGH */

    case MACH:
	if (!usedefault) {
	    if (token() != ID)
		continue;
	    /*
	     * Allow match either for user's input host name
	     * or official hostname.  Also allow match of
	     * incompletely-specified host in local domain.
	     */
	    if (strcasecmp(host, tokval) == 0)
		goto match;
	    if (strcasecmp(hostname, tokval) == 0)
		goto match;
	    if ((tmp = strchr(hostname, '.')) != NULL &&
		tmp++ &&
		strcasecmp(tmp, mydomain) == 0 &&
		strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
		tokval[tmp - hostname] == '\0')
		goto match;
	    if ((tmp = strchr(host, '.')) != NULL &&
		tmp++ &&
		strcasecmp(tmp, mydomain) == 0 &&
		strncasecmp(host, tokval, tmp - host) == 0 &&
		tokval[tmp - host] == '\0')
		goto match;
	    continue;
	}
    match:
	while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {

	case LOGIN:
	    if (token()) {
		if (*aname == 0) {
		    *aname = strdup(tokval);
		} else {
		    if (strcmp(*aname, tokval))
			goto next;
		}
	    }
	    break;
	case PASSWD:
	    if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
		fstat(fileno(cfile), &stb) >= 0 &&
		(stb.st_mode & 077) != 0) {
		warnx("Error: .netrc file is readable by others.");
		warnx("Remove password or make file unreadable by others.");
		goto bad;
	    }
	    if (token() && *apass == 0) {
		*apass = strdup(tokval);
	    }
	    break;
	case ACCOUNT:
	    if (fstat(fileno(cfile), &stb) >= 0
		&& (stb.st_mode & 077) != 0) {
		warnx("Error: .netrc file is readable by others.");
		warnx("Remove account or make file unreadable by others.");
		goto bad;
	    }
	    if (token() && *aacct == 0) {
		*aacct = strdup(tokval);
	    }
	    break;
	case MACDEF:
	    if (proxy) {
		fclose(cfile);
		return (0);
	    }
	    while ((c=getc(cfile)) != EOF &&
		   (c == ' ' || c == '\t'));
	    if (c == EOF || c == '\n') {
		printf("Missing macdef name argument.\n");
		goto bad;
	    }
	    if (macnum == 16) {
		printf("Limit of 16 macros have already been defined\n");
		goto bad;
	    }
	    tmp = macros[macnum].mac_name;
	    *tmp++ = c;
	    for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
		     !isspace(c); ++i) {
		*tmp++ = c;
	    }
	    if (c == EOF) {
		printf("Macro definition missing null line terminator.\n");
		goto bad;
	    }
	    *tmp = '\0';
	    if (c != '\n') {
		while ((c=getc(cfile)) != EOF && c != '\n');
	    }
	    if (c == EOF) {
		printf("Macro definition missing null line terminator.\n");
		goto bad;
	    }
	    if (macnum == 0) {
		macros[macnum].mac_start = macbuf;
	    }
	    else {
		macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
	    }
	    tmp = macros[macnum].mac_start;
	    while (tmp != macbuf + 4096) {
		if ((c=getc(cfile)) == EOF) {
		    printf("Macro definition missing null line terminator.\n");
		    goto bad;
		}
		*tmp = c;
		if (*tmp == '\n') {
		    if (*(tmp-1) == '\0') {
			macros[macnum++].mac_end = tmp - 1;
			break;
		    }
		    *tmp = '\0';
		}
		tmp++;
	    }
	    if (tmp == macbuf + 4096) {
		printf("4K macro buffer exceeded\n");
		goto bad;
	    }
	    break;
	case PROT:
	    token();
	    if(doencrypt == 0 && sec_request_prot(tokval) < 0)
		warnx("Unknown protection level \"%s\"", tokval);
	    break;
	default:
	    warnx("Unknown .netrc keyword %s", tokval);
	    break;
	}
	goto done;
    }
done:
    fclose(cfile);
    return (0);
bad:
    fclose(cfile);
    return (-1);
}