/* FIXME: The error code returned here is never checked. */ static int sec_set_protection_level(struct connectdata *conn) { int code; char *pbsz; static unsigned int buffer_size = 1 << 20; /* 1048576 */ enum protection_level level = conn->request_data_prot; DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); if(!conn->sec_complete) { infof(conn->data, "Trying to change the protection level after the" "completion of the data exchange.\n"); return -1; } /* Bail out if we try to set up the same level */ if(conn->data_prot == level) return 0; if(level) { code = ftp_send_command(conn, "PBSZ %u", buffer_size); if(code < 0) return -1; if(code/100 != 2) { failf(conn->data, "Failed to set the protection's buffer size."); return -1; } conn->buffer_size = buffer_size; pbsz = strstr(conn->data->state.buffer, "PBSZ="); if(pbsz) { /* ignore return code, use default value if it fails */ (void)sscanf(pbsz, "PBSZ=%u", &buffer_size); if(buffer_size < conn->buffer_size) conn->buffer_size = buffer_size; } } /* Now try to negiociate the protection level. */ code = ftp_send_command(conn, "PROT %c", level_to_char(level)); if(code < 0) return -1; if(code/100 != 2) { failf(conn->data, "Failed to set the protection level."); return -1; } conn->data_prot = level; if(level == PROT_PRIVATE) conn->command_prot = level; return 0; }
int ftp_disconnect(ftp_t* ftp) { char answer[MAX_STRING_SIZE]; if(ftp_read_answer(ftp, answer, MAX_STRING_SIZE) < 0) { printf("Error in disconnecing from server\n"); return -1; } if(ftp_send_command(ftp, "quit\n", strlen("quit\n")) < 0) { printf("Error in sending quit command\n"); return -1; } if(close(ftp->socketfd) < 0) { printf("Failed to close ftp socket.\n"); return -1; } if(close(ftp->datafd) < 0) { printf("Failed to close ftp data socket.\n"); return -1; } printf("Disconnected from server.\n"); return 0; }
int ftp_login_host(ftp_t* ftp) { char command[6 + strlen(ftp->username)]; char answer[MAX_STRING_SIZE]; sprintf(command,"user %s\n", ftp->username); if(ftp_send_command(ftp, command, strlen(command)) < 0) { printf("Error while sending login information\n"); return -1; } if(ftp_read_answer(ftp, answer, MAX_STRING_SIZE) < 0) { printf("Error while receiving answer from login information \n"); return -1; } sprintf(command,"pass %s\n", ftp->password); if(ftp_send_command(ftp, command, strlen(command)) < 0) { printf("Error while sending login information\n"); return -1; } if(ftp_read_answer(ftp, answer, MAX_STRING_SIZE) < 0) { printf("Error while receiving answer from login information \n"); return -1; } int replyCode; sscanf(answer, "%d", &replyCode); if(replyCode == LOGIN_FAIL) { /* Failed to login */ printf("Wrong username/password combination.\n"); return -1; } printf("Logged in to server %s.\n",ftp->server_address); return 0; }
int ftp_retr_file(ftp_t* ftp) { char command[6+strlen(ftp->path_to_file)]; char answer[MAX_STRING_SIZE]; sprintf(command, "retr %s\n", ftp->path_to_file); printf("Requesting file %s\n",basename(ftp->path_to_file)); if(ftp_send_command(ftp, command, 6+strlen(ftp->path_to_file)) < 0) { printf("Error in requesting file from server\n"); return -1; } if(ftp_read_answer(ftp, answer, MAX_STRING_SIZE) < 0) { printf("Error in reading answer from file request from server\n"); return -1; } int replyCode; sscanf(answer, "%d", &replyCode); if(replyCode == OPEN_FILE_FAIL) { /* Failed to find file */ printf("Couldn't find file %s in server.\n", ftp->path_to_file); return -1; } else if(replyCode == OPEN_FILE_SUCCESS) { /* Find the file size to export it */ char* beg = strrchr(answer,'('); char sizeInfo[MAX_STRING_SIZE]; strcpy(sizeInfo, beg); int size; sscanf(sizeInfo, "(%d bytes).", &size); ftp->file_size = size; #ifdef DEBUG printf("DEBUG : Size Info: %d bytes\n", size); #endif } #ifdef DEBUG printf("%s\n", answer); #endif return 0; }
int ftp_set_passive_mode(ftp_t* ftp) { char answer[MAX_STRING_SIZE]; int ip1, ip2, ip3, ip4; int port1, port2; if(ftp_send_command(ftp, "pasv\n", strlen("pasv\n")) < 0) { printf("Error while switching to passive mode\n"); return -1; } if(ftp_read_answer(ftp, answer, MAX_STRING_SIZE) < 0) { printf("Error while receiving answer from switching to passive mode \n"); return -1; } #ifdef DEBUG printf("%s", answer); #endif if ((sscanf(answer, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)", &ip1, &ip2, &ip3, &ip4, &port1, &port2)) < 0) { printf("Error while parsing pasv answer from the server.\n"); return -1; } char ip[15]; int port = 256*port1+port2; sprintf(ip, "%d.%d.%d.%d", ip1, ip2, ip3, ip4); #ifdef DEBUG printf("IP: %s Port: %d\n", ip, port); #endif int datafd = ftp_connect_socket(ip, port); if(datafd < 0) { printf("Error while connecting to data socket\n"); return -1; } ftp->datafd = datafd; return 0; }
static CURLcode choose_mech(struct connectdata *conn) { int ret; struct Curl_easy *data = conn->data; void *tmp_allocation; const struct Curl_sec_client_mech *mech = &Curl_krb5_client_mech; tmp_allocation = realloc(conn->app_data, mech->size); if(tmp_allocation == NULL) { failf(data, "Failed realloc of size %u", mech->size); mech = NULL; return CURLE_OUT_OF_MEMORY; } conn->app_data = tmp_allocation; if(mech->init) { ret = mech->init(conn->app_data); if(ret) { infof(data, "Failed initialization for %s. Skipping it.\n", mech->name); return CURLE_FAILED_INIT; } } infof(data, "Trying mechanism %s...\n", mech->name); ret = ftp_send_command(conn, "AUTH %s", mech->name); if(ret < 0) /* FIXME: This error is too generic but it is OK for now. */ return CURLE_COULDNT_CONNECT; if(ret/100 != 3) { switch(ret) { case 504: infof(data, "Mechanism %s is not supported by the server (server " "returned ftp code: 504).\n", mech->name); break; case 534: infof(data, "Mechanism %s was rejected by the server (server returned " "ftp code: 534).\n", mech->name); break; default: if(ret/100 == 5) { infof(data, "server does not support the security extensions\n"); return CURLE_USE_SSL_FAILED; } break; } return CURLE_LOGIN_DENIED; } /* Authenticate */ ret = mech->auth(conn->app_data, conn); if(ret != AUTH_CONTINUE) { if(ret != AUTH_OK) { /* Mechanism has dumped the error to stderr, don't error here. */ return -1; } DEBUGASSERT(ret == AUTH_OK); conn->mech = mech; conn->sec_complete = 1; conn->recv[FIRSTSOCKET] = sec_recv; conn->send[FIRSTSOCKET] = sec_send; conn->recv[SECONDARYSOCKET] = sec_recv; conn->send[SECONDARYSOCKET] = sec_send; conn->command_prot = PROT_SAFE; /* Set the requested protection level */ /* BLOCKING */ (void)sec_set_protection_level(conn); } return CURLE_OK; }