📄 ftp.c
字号:
return (line);}int cfputs(ftp_t *x, char *line){ char buffer[310]; if (debug) fprintf (stderr, ">>> CLI: %s\n", line); snprintf (buffer, sizeof(buffer) - 2, "%s\r\n", line); write(1, buffer, strlen(buffer)); return (0);}char *sfgets(ftp_t *x, char *line, int size){ char *p; *line = 0; if ((p = readline_fd(x, x->fd.server, line, size)) == NULL) return (NULL); else if (debug != 0) fprintf (stderr, "SVR >>>: %s\n", p); return (line);}int sfputs(ftp_t *x, char *format, ...){ int len; char buffer[310]; va_list ap; va_start(ap, format); vsnprintf (buffer, sizeof(buffer) - 10, format, ap); va_end(ap); if (debug) fprintf (stderr, ">>> SVR: %s\n", buffer); /* * There are firewalls that don't like command to be split in * two packets. Notice: the `- 10' above is really important * to protect the proxy against buffer overflows. */ strcat(buffer, "\r\n"); len = strlen(buffer); /* * SIGPIPE is catched but then ignored, we have to handle it * one our own now -- 24APR02asg */ if (write(x->fd.server, buffer, len) != len) { syslog(LOG_NOTICE, "-ERR: error writing control connect, error= %s", strerror(errno)); exit (1); }/* * write(x->fd.server, buffer, strlen(buffer)); * write(x->fd.server, "\r\n", 2); */ return (0);}int sfputc(ftp_t *x, char *command, char *parameter, char *line, int size, char **here){ int rc; char *p, buffer[300]; if (command != NULL && *command != 0) { if (parameter != NULL && *parameter != 0) snprintf (buffer, sizeof(buffer) - 2, "%s %s", command, skip_ws(parameter)); else copy_string(buffer, command, sizeof(buffer)); sfputs(x, "%s", buffer); } if (sfgets(x, line, size) == NULL) { if (debug != 0) fprintf (stderr, "server disappered in sfputc(), pos #1\n"); return (-1); } else if (strlen(line) < 3) { if (debug != 0) fprintf (stderr, "short server reply in sfputc()\n"); return (-1); } rc = atoi(line); if (line[3] != ' ' && line[3] != 0) { while (1) { if (sfgets(x, line, size) == NULL) { syslog(LOG_NOTICE, "-ERR: lost server while reading client greeting: %s", x->server.name); exit (1); } if (strlen(line) < 3) /* line too short to be response's last line */ ; else if (line[3] != ' ' && line[3] != 0) /* neither white space nor EOL at position #4 */ ; else if (line[0] >= '0' && line[0] <= '9' && atoi(line) == rc) break; /* status code followed by EOL or blank detected */ } } if (here != NULL) { p = skip_ws(&line[3]); *here = p; } return (rc);}int doquit(ftp_t *x){ int rc; char resp[200]; if ((rc = sfputc(x, "QUIT", "", resp, sizeof(resp), NULL)) != 221) syslog(LOG_NOTICE, "unexpected resonse to QUIT: %s", resp); cfputs(x, "221 goodbye"); syslog(LOG_NOTICE, "%d QUIT", rc); return (0);}char *_getipnum(char *line, char **here, char *ip, int size){ int c, i, k; copy_string(ip, line, size); k = 0; for (i=0; (c = ip[i]) != 0; i++) { if (c == ',') { if (k < 3) { ip[i] = '.'; k++; } else { ip[i++] = 0; break; } } } if (here != NULL) *here = &line[i]; return (ip);}unsigned long _getport(char *line, char **here){ unsigned long port; char *p; p = line; port = strtoul(p, &p, 10); if (*p != ',') return (0); p++; port = (port << 8) + strtoul(p, &p, 10); if (here != NULL) *here = p; return (port);}int doport(ftp_t *x, char *command, char *par){ int c, rc; char *p, line[200]; dtc_t *ch; ch = &x->ch; _getipnum(par, &p, ch->client.ipnum, sizeof(ch->client.ipnum)); ch->client.port = _getport(p, &p); if (debug) fprintf (stderr, "client listens on %s:%u\n", ch->client.ipnum, ch->client.port); get_interface_info(x->fd.server, ch->outside.ipnum, sizeof(ch->outside.ipnum)); ch->osock = bind_to_port(ch->outside.ipnum, 0); ch->outside.port = get_interface_info(ch->osock, line, sizeof(line)); if (debug) fprintf (stderr, "listening on %s:%u\n", ch->outside.ipnum, ch->outside.port); copy_string(line, ch->outside.ipnum, sizeof(line)); for (p=line; (c = *p) != 0; p++) { if (c == '.') *p = ','; } *p++ = ','; snprintf (p, 20, "%u,%u", ch->outside.port >> 8, ch->outside.port & 0xFF); /* Open port first */ ch->isock = -1; ch->mode = MODE_PORT; ch->state = PORT_LISTEN; /* then send PORT cmd */ rc = sfputc(x, "PORT", line, line, sizeof(line), &p); /* check return code */ if (rc != 200){ cfputs(x, "500 not accepted"); close_ch(x, &x->ch); } else cfputs(x, "200 ok, port allocated");/* if (rc != 200) cfputs(x, "500 not accepted"); else { cfputs(x, "200 ok, port allocated"); ch->isock = -1; ch->mode = MODE_PORT; ch->state = PORT_LISTEN; }*/ *ch->command = 0; return (rc);}int dopasv(ftp_t *x, char *command, char *par){ int c, k, rc; char *p, line[200]; dtc_t *ch; ch = &x->ch; rc = sfputc(x, "PASV", "", line, sizeof(line), &p); if (rc != 227) { cfputs(x, "500 not accepted"); return (0); } /* * Ende der Port-Koordinaten im Server-Response suchen. */ k = strlen(line); while (k > 0 && isdigit(line[k-1]) == 0) k--; if (isdigit(line[k-1])) { line[k--] = 0; while (k > 0 && (isdigit(line[k-1]) || line[k-1] == ',')) k--; } /* * line[k] sollte jetzt auf die erste Ziffer des PASV Response * zeigen. */ if (isdigit(line[k]) == 0) { syslog(LOG_NOTICE, "can't locate passive response: %s", line); cfputs(x, "500 not accepted"); return (0); } /* * Auslesen der PASV IP-Nummer und des Ports. */ p = &line[k]; _getipnum(p, &p, ch->server.ipnum, sizeof(ch->server.ipnum)); ch->server.port = _getport(p, &p); if (debug) fprintf (stderr, "server listens on %s:%u\n", ch->server.ipnum, ch->server.port); get_interface_info(0, ch->inside.ipnum, sizeof(ch->inside.ipnum)); ch->isock = bind_to_port(ch->inside.ipnum, 0); ch->inside.port = get_interface_info(ch->isock, line, sizeof(line)); if (debug) fprintf (stderr, "listening on %s:%u\n", ch->inside.ipnum, ch->inside.port); snprintf (line, sizeof(line) - 2, "227 Entering Passive Mode (%s,%u,%u)", ch->inside.ipnum, ch->inside.port >> 8, ch->inside.port & 0xFF); for (p=line; (c = *p) != 0; p++) { if (c == '.') *p = ','; } cfputs(x, line); ch->osock = -1; ch->mode = MODE_PASSIVE; ch->state = PORT_LISTEN; *ch->command = 0; ch->operation = 0; return (rc);}int dofeat(ftp_t *x){ /* * Not so easy because we have to align with the server response. */ int rc; char *p, word[80], serverfeature[80], line[300]; static char *proxyfeatlist = "SIZE:MDTM"; sfputs(x, "%s", "FEAT"); if (sfgets(x, line, sizeof(line)) == NULL) { syslog(LOG_NOTICE, "monitor: server not responding"); exit (1); } rc = atoi(line); if (rc != 211) { /* kein FEAT Support */ ; cfputs(x, "502 command not implemented"); return (1); } cfputs(x, "211-feature list follows"); while (1) { if (sfgets(x, line, sizeof(line)) == NULL) { syslog(LOG_NOTICE, "lost server in FEAT response"); exit (1); } else if (*line != ' ') { /* * RFC2389 specifies exactly one space in this * multi-line response. Nothing else. */ break; } /* Get feature from server response ... */ copy_string(serverfeature, line, sizeof(serverfeature)); strupr(serverfeature); /* ... and compare it against our feature list */ p = proxyfeatlist; while (*get_quoted(&p, ':', word, sizeof(word)) != 0) { if (strcmp(word, serverfeature) == 0) { snprintf (line, sizeof(line) - 4, " %s", word); cfputs(x, line); break; } } } cfputs(x, "211 end"); return (0);}int setvar(ftp_t *x, char *var, char *value){ char varname[200]; #if defined SOLARIS snprintf (varname, sizeof(varname) - 2, "%s%s=%s", x->config->varname, var, value != NULL? value: ""); putenv(varname); #else snprintf (varname, sizeof(varname) - 2, "%s%s", x->config->varname, var); setenv(varname, value != NULL? value: "", 1); #endif return (0);}int set_variables(ftp_t *x){ char val[200]; setvar(x, "INTERFACE", x->interface); snprintf (val, sizeof(val) - 2, "%u", x->port); setvar(x, "PORT", val); setvar(x, "CLIENT", x->client_ip); setvar(x, "CLIENTNAME", x->client); setvar(x, "SERVER", x->server.ipnum); snprintf (val, sizeof(val) - 2, "%u", x->server.port); setvar(x, "SERVERPORT", val); setvar(x, "SERVERNAME", x->server.name); setvar(x, "SERVERLOGIN", x->username); setvar(x, "USERNAME", x->local.username); setvar(x, "PASSWD", x->local.password); return (0);}int run_acp(ftp_t *x){ int rc, pid, pfd[2]; char line[300]; if (*x->config->acp == 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 acp: %s", strerror(errno)); exit (1); } else if (pid == 0) { int argc; char *argv[32]; close(0); /* Das acp kann nicht vom client lesen. */ dup2(pfd[1], 2); /* stderr wird vom parent gelesen. */ close(pfd[0]); set_variables(x); copy_string(line, x->config->acp, sizeof(line)); argc = split(line, argv, ' ', 30); argv[argc] = NULL; execvp(argv[0], argv); syslog(LOG_NOTICE, "-ERR: can't exec acp %s: %s", argv[0], strerror(errno)); exit (1); } else { int len; char message[300]; close(pfd[1]); *message = 0; if ((len = read(pfd[0], message, sizeof(message) - 2)) < 0) len = 0; message[len] = 0; noctrl(message); close(pfd[0]); if (waitpid(pid, &rc, 0) < 0) { syslog(LOG_NOTICE, "-ERR: error while waiting for acp: %s", strerror(errno)); exit (1); } rc = WIFEXITED(rc) != 0? WEXITSTATUS(rc): 1; if (*message == 0) copy_string(message, rc == 0? "access granted": "access denied", sizeof(message)); if (*message != 0) syslog(LOG_NOTICE, "%s (rc= %d)", message, rc); } return (rc);}static char *getvarname(char **here, char *var, int size){ int c, k; size = size - 2; k = 0; while ((c = **here) != 0) { *here += 1; if (c == ' ' || c == '\t' || c == '=') break; if (k < size) var[k++] = c; } var[k] = 0; strupr(var); *here = skip_ws(*here); return (var);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -