43 #ifndef CURL_DISABLE_FTP
46 #define _MPRINTF_REPLACE
67 #define min(a, b) ((a) < (b) ? (a) : (b))
70 enum protection_level
level;
73 { prot_clear,
"clear" },
74 { prot_safe,
"safe" },
75 { prot_confidential,
"confidential" },
76 { prot_private,
"private" }
79 static enum protection_level
80 name_to_level(
const char *
name)
83 for(i = 0; i < (
int)
sizeof(level_names)/(
int)
sizeof(level_names[0]); i++)
84 if(!
strncasecmp(level_names[i].name, name, strlen(name)))
85 return level_names[
i].level;
86 return (
enum protection_level)-1;
102 if(conn->sec_complete && conn->data_prot) {
113 block_read(
int fd,
void *buf,
size_t len)
115 unsigned char *
p = buf;
118 b = read(fd, p, len);
126 return p - (
unsigned char*)buf;
130 block_write(
int fd,
void *buf,
size_t len)
132 unsigned char *p = buf;
135 b = write(fd, p, len);
141 return p - (
unsigned char*)buf;
146 int fd,
struct krb4buffer *buf)
151 b = block_read(fd, &len,
sizeof(len));
157 buf->data = realloc(buf->data, len);
158 b = block_read(fd, buf->data, len);
163 buf->size = (conn->mech->decode)(conn->app_data, buf->
data, len,
164 conn->data_prot, conn);
170 buffer_read(
struct krb4buffer *buf,
void *
data,
size_t len)
172 len =
min(len, buf->size - buf->index);
173 memcpy(data, (
char*)buf->data + buf->index, len);
179 buffer_write(
struct krb4buffer *buf,
void *data,
size_t len)
181 if(buf->index + len > buf->size) {
183 if(buf->data ==
NULL)
186 tmp = realloc(buf->data, buf->index + len);
190 buf->size = buf->index +
len;
192 memcpy((
char*)buf->data + buf->index, data, len);
203 if(conn->sec_complete == 0 || conn->data_prot == 0)
204 return read(fd, buffer, length);
206 if(conn->in_buffer.eof_flag){
207 conn->in_buffer.eof_flag = 0;
211 len = buffer_read(&conn->in_buffer, buffer, length);
214 buffer = (
char*)buffer + len;
217 if(sec_get_data(conn, fd, &conn->in_buffer) < 0)
219 if(conn->in_buffer.
size == 0) {
221 conn->in_buffer.eof_flag = 1;
224 len = buffer_read(&conn->in_buffer, buffer, length);
227 buffer = (
char*)buffer + len;
233 sec_send(
struct connectdata *conn,
int fd,
char *from,
int length)
237 bytes = (conn->mech->encode)(conn->app_data, from, length, conn->data_prot,
239 bytes = htonl(bytes);
240 block_write(fd, &bytes,
sizeof(bytes));
241 block_write(fd, buf, ntohl(bytes));
249 if(conn->data_prot != prot_clear) {
250 if(conn->out_buffer.index > 0){
252 conn->out_buffer.
data, conn->out_buffer.index);
253 conn->out_buffer.index = 0;
255 sec_send(conn, fd,
NULL, 0);
263 int len = conn->buffer_size;
266 if(conn->data_prot == prot_clear)
267 return write(fd, buffer, length);
269 len -= (conn->mech->overhead)(conn->app_data, conn->data_prot, len);
273 sec_send(conn, fd, buffer, len);
285 if(conn->data_prot == prot_clear)
288 buffer_write(&conn->out_buffer, &ch, 1);
289 if(c ==
'\n' || conn->out_buffer.index >= 1024 ) {
291 conn->out_buffer.index);
292 conn->out_buffer.index = 0;
304 buf = malloc(strlen(s));
307 len = (conn->mech->decode)(conn->app_data, buf, len, level, conn);
316 sscanf(buf,
"%d", &code);
317 if(buf[len-1] ==
'\n')
324 enum protection_level
327 enum protection_level old = conn->command_prot;
328 conn->command_prot =
level;
333 sec_prot_internal(
struct connectdata *conn,
int level)
336 unsigned int s = 1048576;
339 if(!conn->sec_complete){
340 infof(conn->
data,
"No security data exchange has taken place.\n");
353 failf(conn->
data,
"Failed to set protection buffer size.");
356 conn->buffer_size =
s;
360 sscanf(p,
"PBSZ=%u", &s);
362 conn->buffer_size =
s;
372 failf(conn->
data,
"Failed to set protection level.");
376 conn->data_prot = (
enum protection_level)level;
383 if(conn->sec_complete && conn->data_prot != conn->request_data_prot)
384 sec_prot_internal(conn, conn->request_data_prot);
391 int l = name_to_level(level);
394 conn->request_data_prot = (
enum protection_level)l;
407 for(m = mechs; *m && (*m)->
name; m++) {
410 tmp = realloc(conn->app_data, (*m)->
size);
412 failf (data,
"realloc %u failed", (*m)->size);
415 conn->app_data = tmp;
417 if((*m)->init && (*(*m)->init)(conn->app_data) != 0) {
418 infof(data,
"Skipping %s...\n", (*m)->name);
421 infof(data,
"Trying %s...\n", (*m)->name);
433 "%s is not supported by the server.\n", (*m)->name);
436 infof(data,
"%s rejected as security mechanism.\n", (*m)->name);
440 infof(data,
"The server doesn't support the FTP "
441 "security extensions.\n");
449 ret = (*(*m)->auth)(conn->app_data, conn);
458 conn->sec_complete = 1;
459 conn->command_prot = prot_safe;
469 if (conn->mech !=
NULL) {
471 (conn->mech->end)(conn->app_data);
472 memset(conn->app_data, 0, conn->mech->
size);
473 free(conn->app_data);
474 conn->app_data =
NULL;
476 conn->sec_complete = 0;
477 conn->data_prot = (
enum protection_level)0;
int Curl_sec_read_msg(struct connectdata *conn, char *, int)
void Curl_sec_end(struct connectdata *)
struct Curl_sec_client_mech Curl_krb4_client_mech
CURLcode Curl_GetFTPResponse(ssize_t *nreadp, struct connectdata *conn, int *ftpcode)
int Curl_sec_write(struct connectdata *conn, int, char *, int)
size_t Curl_base64_decode(const char *src, char *dest)
int Curl_sec_read(struct connectdata *conn, int, void *, int)
CURLcode Curl_ftpsendf(struct connectdata *conn, const char *fmt,...)
int Curl_sec_request_prot(struct connectdata *conn, const char *level)
GLsizei GLsizei GLenum GLenum const GLvoid * data
int Curl_sec_fflush_fd(struct connectdata *conn, int fd)
void Curl_sec_set_protection_level(struct connectdata *conn)
struct SessionHandle * data
int Curl_sec_getc(struct connectdata *conn, FILE *)
enum protection_level Curl_set_command_prot(struct connectdata *, enum protection_level)
GLsizei const GLcharARB const GLint * length
int Curl_sec_putc(struct connectdata *conn, int, FILE *)
int Curl_sec_login(struct connectdata *)