📄 ftp.c
字号:
int run_ctp(ftp_t *x){ int rc, pid, pfd[2]; char line[300]; FILE *fp; if (*x->config->ctp == 0) return (0); rc = 0; if (pipe(pfd) != 0) { syslog(LOG_NOTICE, "-ERR: can't pipe: %s", strerror(errno)); exit (1); } else if ((pid = fork()) < 0) { syslog(LOG_NOTICE, "-ERR: can't fork trp: %s", strerror(errno)); exit (1); } else if (pid == 0) { int argc; char *argv[32]; close(0); /* Das trp kann nicht vom client lesen. */ dup2(pfd[1], 1); /* stdout wird vom parent gelesen. */ close(pfd[0]); set_variables(x); copy_string(line, x->config->ctp, sizeof(line)); argc = split(line, argv, ' ', 30); argv[argc] = NULL; execvp(argv[0], argv); syslog(LOG_NOTICE, "-ERR: can't exec trp %s: %s", argv[0], strerror(errno)); exit (1); } else { char *p, var[80], line[300]; close(pfd[1]); fp = fdopen(pfd[0], "r"); while (fgets(line, sizeof(line), fp)) { p = skip_ws(noctrl(line)); getvarname(&p, var, sizeof(var)); if (strcmp(var, "SERVERNAME") == 0 || strcmp(var, "SERVER") == 0) copy_string(x->server.name, p, sizeof(x->server.name)); else if (strcmp(var, "SERVERLOGIN") == 0 || strcmp(var, "LOGIN") == 0) copy_string(x->username, p, sizeof(x->username)); else if (strcmp(var, "SERVERPASSWD") == 0 || strcmp(var, "PASSWD") == 0) copy_string(x->password, p, sizeof(x->password)); else if (strcmp(var, "SERVERPORT") == 0 || strcmp(var, "PORT") == 0) x->server.port = atoi(p); /* * Enable the trp to send error messages. */ else if (strcmp(var, "-ERR") == 0 || strcmp(var, "-ERR:") == 0) { syslog(LOG_NOTICE, "-ERR: %s", skip_ws(p)); exit (1); } } fclose(fp); /* * In standalone mode we do not receive the SIGCHLD because * we set it to SIG_IGN -- 030406asg */ if (x->config->standalone == 0 && waitpid(pid, &rc, 0) < 0) { syslog(LOG_NOTICE, "-ERR: error while waiting for trp: %s", strerror(errno)); exit (1); } rc = WIFEXITED(rc) != 0? WEXITSTATUS(rc): 1; if (rc != 0) { syslog(LOG_NOTICE, "-ERR: trp signals error condition, rc= %d", rc); exit (1); } } return (rc);}int get_ftpdir(ftp_t *x){ int rc, len; char *p, *start, line[300]; static char *quotes = "'\"'`"; sfputs(x, "%s", "PWD"); if (sfgets(x, line, sizeof(line)) == NULL) { syslog(LOG_NOTICE, "monitor: server not responding"); exit (1); } rc = strtol(line, &p, 10); if (rc != 257) { syslog(LOG_NOTICE, "monitor: PWD status: %d", rc); exit (1); } p = skip_ws(p); if (*p == 0) { syslog(LOG_NOTICE, "monitor: directory unset"); exit (1); } if ((start = strchr(p, '/')) == NULL) { syslog(LOG_NOTICE, "monitor: can't find directory in string: %s", p); exit (1); } get_word(&start, x->cwd, sizeof(x->cwd)); if ((len = strlen(x->cwd)) > 0 && strchr(quotes, x->cwd[len-1]) != NULL) x->cwd[len - 1] = 0; if (*x->cwd != '/') { syslog(LOG_NOTICE, "monitor: invalid path: %s", x->cwd); exit (1); } syslog(LOG_NOTICE, "cwd: %s", x->cwd); return (0);}int get_ftppath(ftp_t *x, char *path){ int i, k, n, m; char cwp[200], ftpdir[200], pbuf[200]; char *part[DIR_MAXDEPTH+5], *dir[DIR_MAXDEPTH+5]; /* * Zuerst wird das aktuelle Verzeichnis (der ftppath) in seine * Einzelteile zerlegt ... */ if (*path == '/') { /* * ... Ausnahme: die path-Angabe ist absolut ... */ dir[0] = ""; n = 1; } else { copy_string(ftpdir, x->cwd, sizeof(ftpdir)); if (*ftpdir != 0 && strcmp(ftpdir, "/") != 0) n = split(ftpdir, part, '/', DIR_MAXDEPTH); else { dir[0] = ""; n = 1; } } /* * ... danach der path. Die path Teile werden unter Beachtung * der ueblichen Regeln an die Teile des aktuellen Verzeichnisses * angehangen ... */ copy_string(pbuf, path, sizeof(pbuf)); m = split(pbuf, dir, '/', 15); for (i=0; i<m; i++) { if (*dir[i] == 0) /* zwei aufeinander folgende `/' */ ; else if (strcmp(dir[i], ".") == 0) /* nichts */ ; else if (strcmp(dir[i], "..") == 0) { if (n > 1) n = n - 1; } else part[n++] = dir[i]; if (n < 1 || n >= DIR_MAXDEPTH) return (1); /* ungueltiges Verzeichnis */ } /* * ... und das Ergebnis wieder zusammengesetzt. */ if (n <= 1) { strcpy(cwp, "/"); } else { k = 0; for (i=1; i<n; i++) { if ((k + strlen(part[i]) + 1 + 2) >= sizeof(dir)) return (1); /* Name zu lang */ cwp[k++] = '/'; strcpy(&cwp[k], part[i]); k += strlen(&cwp[k]); } cwp[k] = 0; } /* * Der normalisierte path auf das Objekt (Datei oder Verzeichnis, * ist hier egal) ist fertig. */ copy_string(x->filepath, cwp, sizeof(x->filepath)); return (0);}int run_ccp(ftp_t *x, char *cmd, char *par){ int rc, pid, pfd[2], lfd[2]; char message[300], line[300]; /* * Wenn kein ccp angegeben ist ist alles erlaubt. */ if (*x->config->ccp == 0) return (CCP_OK); /* * Der Vorgang fuer ccp's ist fast gleich mit dem fuer acp's. */ rc = 0; if (pipe(pfd) != 0 || pipe(lfd)) { syslog(LOG_NOTICE, "-ERR: can't pipe: %s", strerror(errno)); exit (1); } else if ((pid = fork()) < 0) { syslog(LOG_NOTICE, "-ERR: can't fork ccp: %s", strerror(errno)); exit (1); } else if (pid == 0) { int argc; char *argv[32]; dup2(pfd[1], 2); /* stderr nach FTP Client */ close(pfd[0]); dup2(lfd[1], 1); /* stdout nach syslog */ close(lfd[0]); close(0); set_variables(x); setvar(x, "COMMAND", cmd); setvar(x, "PARAMETER", par); setvar(x, "SESSION", x->session); snprintf (line, sizeof(line) - 2, "%d", x->ccpcoll); setvar(x, "CCPCOLL", line); setvar(x, "FTPHOME", x->home); setvar(x, "FTPPATH", x->filepath); copy_string(line, x->config->ccp, sizeof(line)); argc = split(line, argv, ' ', 30); argv[argc] = NULL; execvp(argv[0], argv); syslog(LOG_NOTICE, "-ERR: can't exec ccp %s: %s", argv[0], strerror(errno)); exit (1); } else { int len; /* * Nicht gebrauchte fd's schliessen. */ close(pfd[1]); close(lfd[1]); /* * syslog Meldung lesen und entsprechende pipe schliessen. */ *message = 0; if ((len = read(lfd[0], message, sizeof(message) - 2)) < 0) len = 0; message[len] = 0; noctrl(message); close(lfd[0]); if (*message != 0) syslog(LOG_NOTICE, "%s", message); /* * Fehlermeldung lesen, pipe schliessen. */ *message = 0; if ((len = read(pfd[0], message, sizeof(message) - 2)) < 0) len = 0; message[len] = 0; noctrl(message); close(pfd[0]); /* * return code holen. */ if (waitpid(pid, &rc, 0) < 0) { syslog(LOG_NOTICE, "-ERR: error while waiting for ccp: %s", strerror(errno)); exit (1); } rc = WIFEXITED(rc) != 0? WEXITSTATUS(rc): 1; if (rc == 0) return (CCP_OK); if (*message == 0) copy_string(message, "permission denied", sizeof(message));/* * snprintf (command, sizeof(command) - 2, "%s%s%s", cmd, (par != 0? " ": ""), par); * syslog(LOG_NOTICE, "ccp: -ERR: %s@%s: %s: %s: rc= %d", * x->username, x->server.name, * command, message, rc); */ } x->ccpcoll++; if (isdigit(*message)) cfputs(x, message); else { snprintf (line, sizeof(line) - 2, "553 %s", message); cfputs(x, line); }/* cfputs(x, "553 permission denied."); */ return (CCP_ERROR);} /* * dologin() accepts now blanks with in and at the end of * passwords - 22JAN02asg */int dologin(ftp_t *x){ int c, i, rc; char *p, word[80], line[300]; struct hostent *hostp; struct sockaddr_in saddr; while (1) { if (readline_fd(x, 0, line, sizeof(line)) == NULL) return (1); if (x->config->allow_passwdblanks == 0) p = noctrl(line); else { p = line; for (i=strlen(line)-1; i>=0; i--) { if ((c = line[i]) != '\n' && c != '\r') { line[i+1] = 0; break; } } } get_word(&p, word, sizeof(word)); strupr(word); if (strcmp(word, "USER") == 0) { get_word(&p, x->username, sizeof(x->username)); cfputs(x, "331 password required"); } else if (strcmp(word, "PASS") == 0) { if (*x->username == 0) { cfputs(x, "503 give USER first"); continue; } if (x->config->allow_passwdblanks == 0) get_word(&p, x->password, sizeof(x->password)); else copy_string(x->password, p, sizeof(x->password)); break; } else if (strcmp(word, "QUIT") == 0) { cfputs(x, "221 goodbye"); return (2); } else { cfputs(x, "530 login first"); } } if (*x->config->ctp != 0) { /* * We are extremly liberate here with server selection * if we have a dynamic control program, we accept * anything here -- 030404asg */ if ((p = strchr(x->username, '@')) == NULL && (p = strchr(x->username, '%')) == NULL) *x->server.name = 0; else if (x->config->use_last_at == 0) { *p++ = 0; copy_string(x->server.name, p, sizeof(x->server.name)); } else { if ((p = strrchr(x->username, '@')) == NULL) p = strrchr(x->username, '%'); *p++ = 0; copy_string(x->server.name, p, sizeof(x->server.name)); } } else if (x->config->selectserver == 0) { if ((p = strchr(x->username, '@')) != NULL && (p = strchr(x->username, '%')) != NULL) { cfputs(x, "500 service unavailable"); syslog(LOG_NOTICE, "-ERR: hostname supplied: %s", p); exit (1); } copy_string(x->server.name, x->config->server, sizeof(x->server.name)); } else { /* * Normally we search for the first '@' so that the client can * not use "proxy hopping". The option "-u" can override * this behaviour. */ if (x->config->use_last_at == 0) { if ((p = strchr(x->username, '@')) == NULL && (p = strchr(x->username, '%')) == NULL) { cfputs(x, "500 service unavailable"); syslog(LOG_NOTICE, "-ERR: missing hostname"); exit (1); } } else { if ((p = strrchr(x->username, '@')) == NULL && (p = strrchr(x->username, '%')) == NULL) { cfputs(x, "500 service unavailable"); syslog(LOG_NOTICE, "-ERR: missing hostname"); exit (1); } } *p++ = 0; copy_string(x->server.name, p, sizeof(x->server.name)); /* * Den Server auf der Serverliste suchen, wenn eine Liste * vorhanden ist. *//* * Checking the server against the given list is done later now, * see below. Code quoted -- 030404asg * * if ((p = x->config->serverlist) != NULL && *p != 0) { * int permitted; * char pattern[80]; * * permitted = 0; * while ((p = skip_ws(p)), *get_quoted(&p, ',', pattern, sizeof(pattern)) != 0) { * noctrl(pattern); * if (strpcmp(x->server.name, pattern) == 0) { * permitted = 1; * break; * } * } * * if (permitted == 0) { * cfputs(x, "500 service unavailable"); * syslog(LOG_NOTICE, "-ERR: hostname not permitted: %s", x->server.name); * exit (1); * } * } */ } /* * Wenn vorhanden Proxy Login und Passwort auslesen. */ if ((p = strchr(x->username, ':')) != NULL) { *p++ = 0; copy_string(x->local.username, x->username, sizeof(x->local.username));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -