void _iris_progress_monitor_handle_message (IrisMessage *message, gpointer user_data) { IrisProgressWatch *watch = user_data; IrisProgressMonitor *progress_monitor = watch->monitor; IrisProgressMonitorInterface *iface; if (watch->cancelled || watch->complete) if (message->what != IRIS_PROGRESS_MESSAGE_TITLE) g_warning ("IrisProgressMonitor: watch %lx sent a progress message " "after already sending %s.\n", (gulong)watch, watch->cancelled? "CANCELLED": "COMPLETE"); g_return_if_fail (IRIS_IS_PROGRESS_MONITOR (progress_monitor)); /* Any of these messages indicate that the connections cannot now change. Note that for * watch->chain_flag to be TRUE if watch->task is not of type IrisProcess is an error. * Normally you must be aware that watch->task could be an IrisTask. */ if (watch->chain_flag) { watch->chain_flag = FALSE; watch_chain (progress_monitor, IRIS_PROCESS (watch->task)); } switch (message->what) { case IRIS_PROGRESS_MESSAGE_CANCELLED: handle_cancelled (watch, message); break; case IRIS_PROGRESS_MESSAGE_COMPLETE: handle_complete (watch, message); break; case IRIS_PROGRESS_MESSAGE_PULSE: break; case IRIS_PROGRESS_MESSAGE_FRACTION: handle_fraction (watch, message); break; case IRIS_PROGRESS_MESSAGE_PROCESSED_ITEMS: handle_processed_items (watch, message); break; case IRIS_PROGRESS_MESSAGE_TOTAL_ITEMS: handle_total_items (watch, message); break; case IRIS_PROGRESS_MESSAGE_TITLE: handle_title (watch, message); break; default: g_warn_if_reached (); } /* Chain the message to implementation, after we have processed what we need */ iface = IRIS_PROGRESS_MONITOR_GET_INTERFACE (progress_monitor); iface->handle_message (progress_monitor, watch, message); }
/** * Check an announce phase message and pass to appropriate message handler, * decrypting first if necessary * Returns 1 on success, 0 on error */ int handle_announce_phase(const unsigned char *packet, unsigned char *decrypted, const struct sockaddr_in *receiver, struct finfo_t *finfo, int announce, int open, int regconf) { struct uftp_h *header; const unsigned char *message; int hostidx; unsigned decryptlen, meslen; uint8_t *func; struct in_addr srcaddr; header = (struct uftp_h *)packet; hostidx = find_client(header->srcaddr); if (header->srcaddr == 0) { srcaddr = receiver->sin_addr; } else { srcaddr.s_addr = header->srcaddr; } if ((keytype != KEY_NONE) && (header->func == ENCRYPTED)) { if (hostidx == -1) { log(0, 0, "Got encrypted packet from unknown receiver %s", inet_ntoa(srcaddr)); return 0; } if (!validate_and_decrypt(packet, &decrypted, &decryptlen, mtu, keytype, groupkey, groupsalt, ivlen, hashtype, grouphmackey, hmaclen, sigtype, destlist[hostidx].encinfo->pubkey, destlist[hostidx].encinfo->pubkeylen)) { log1(0, 0, "Rejecting message from %s: decrypt/validate failed", destlist[hostidx].name); return 0; } func = (uint8_t *)decrypted; message = decrypted; meslen = decryptlen; } else { if ((keytype != KEY_NONE) && (header->func == INFO_ACK)) { log1(0, 0, "Rejecting %s message from %s: not encrypted", func_name(header->func), inet_ntoa(srcaddr)); return 0; } func = (uint8_t *)&header->func; message = packet + sizeof(struct uftp_h); meslen = ntohs(header->blsize); } if (*func == ABORT) { handle_abort(message, meslen, hostidx, finfo, &srcaddr); return 1; } if (hostidx == -1) { if (open) { if (*func == REGISTER) { handle_open_register(message, meslen, finfo, receiver, &srcaddr, regconf); } else if (*func == CLIENT_KEY) { handle_open_clientkey(message, meslen, finfo, receiver, &srcaddr); } else { log1(0, 0, "Invalid function: expected " "REGISTER or CLIENT_KEY, got %s", func_name(*func)); } } else { log1(0, 0, "Host %s not in host list", inet_ntoa(srcaddr)); send_abort(finfo, "Not in host list", receiver, &srcaddr, 0, 0); } } else { switch (destlist[hostidx].status) { case DEST_MUTE: if (*func == REGISTER) { handle_register(message, meslen, finfo, receiver, &srcaddr, hostidx, regconf, open); } else if (*func == CLIENT_KEY) { handle_clientkey(message, meslen, finfo, receiver, &srcaddr, hostidx); } else { log1(0, 0, "Invalid function: expected " "REGISTER or CLIENT_KEY, got %s", func_name(*func)); } break; case DEST_REGISTERED: if (*func == INFO_ACK) { handle_info_ack(message, meslen, finfo, receiver, &srcaddr, hostidx, announce); } else if (*func == REGISTER) { handle_register(message, meslen, finfo, receiver, &srcaddr, hostidx, regconf, open); } else if (*func == CLIENT_KEY) { log(0, 0, "Received CLIENT_KEY+ from %s", destlist[hostidx].name); } else if (!announce && (*func == COMPLETE)) { handle_complete(message, meslen, finfo, hostidx); } else { log1(0, 0, "Received invalid message %s from %s", func_name(*func), destlist[hostidx].name); } break; case DEST_ACTIVE: if (*func == REGISTER) { handle_register(message, meslen, finfo, receiver, &srcaddr, hostidx, regconf, open); } else if (*func == CLIENT_KEY) { log(0, 0, "Received CLIENT_KEY+ from %s", destlist[hostidx].name); } else if (*func == INFO_ACK) { finfo->deststate[hostidx].conf_sent = 0; handle_info_ack(message, meslen, finfo, receiver, &srcaddr, hostidx, announce); } else if (!announce && (*func == COMPLETE)) { handle_complete(message, meslen, finfo, hostidx); } else { log1(0, 0, "Received invalid message %s from %s", func_name(*func), destlist[hostidx].name); } break; default: log1(0, 0, "Received invalid message %s from %s", func_name(*func), destlist[hostidx].name); break; } } return 1; }
/** * Check a transfer phase message and pass to appropriate message handler, * decrypting first if necessary * Returns 1 on success, 0 on error */ int handle_transfer_phase(const unsigned char *packet, unsigned char *decrypted, const struct sockaddr_in *receiver, int blocks_this_sec, int section_offset, int pass, int section, struct finfo_t *finfo) { struct uftp_h *header; const unsigned char *message; int hostidx; unsigned int decryptlen, meslen; uint8_t *func; struct in_addr srcaddr; header = (struct uftp_h *)packet; hostidx = find_client(header->srcaddr); srcaddr.s_addr = header->srcaddr; if ((keytype != KEY_NONE) && (header->func == ENCRYPTED)) { if (hostidx == -1) { log1(0, 0, "Host %s not in host list", inet_ntoa(srcaddr)); send_abort(finfo, "Not in host list", receiver, &srcaddr, 0, 0); return 0; } if (!validate_and_decrypt(packet, &decrypted, &decryptlen, mtu, keytype, groupkey, groupsalt, ivlen, hashtype, grouphmackey, hmaclen, sigtype, destlist[hostidx].encinfo->pubkey, destlist[hostidx].encinfo->pubkeylen)) { log1(0, 0, "Rejecting message from %s: decrypt/validate failed", destlist[hostidx].name); return 0; } func = (uint8_t *)decrypted; message = decrypted; meslen = decryptlen; } else { if ((keytype != KEY_NONE) && ((header->func == PRSTATUS) || (header->func == STATUS) || (header->func == COMPLETE) || (header->func == ABORT))) { log1(0, 0, "Rejecting %s message from %s: not encrypted", func_name(header->func), inet_ntoa(srcaddr)); return 0; } func = (uint8_t *)&header->func; message = packet + sizeof(struct uftp_h); meslen = ntohs(header->blsize); } if (*func == ABORT) { handle_abort(message, meslen, hostidx, finfo, &srcaddr); } else if (hostidx == -1) { log1(0, 0, "Host %s not in host list", inet_ntoa(srcaddr)); send_abort(finfo, "Not in host list", receiver, &srcaddr, 0, 0); } else { switch (destlist[hostidx].status) { case DEST_ACTIVE: if (*func == STATUS) { handle_status(message, meslen, finfo, hostidx, blocks_this_sec, section_offset, pass, section); } else if (*func == COMPLETE) { handle_complete(message, meslen, finfo, hostidx); } else if ((destlist[hostidx].clientcnt != -1) && (*func == PRSTATUS)) { handle_prstatus(message, meslen, finfo, hostidx, blocks_this_sec, section_offset, pass, section); } else { log1(0, 0, "Received invalid message %s from %s", func_name(*func), destlist[hostidx].name); } break; case DEST_STATUS: if (*func == COMPLETE) { handle_complete(message, meslen, finfo, hostidx); } else if (*func == STATUS) { handle_status(message, meslen, finfo, hostidx, blocks_this_sec, section_offset, pass, section); } else { log1(0, 0, "Received invalid message %s from %s", func_name(*func), destlist[hostidx].name); } break; case DEST_DONE: if (*func == COMPLETE) { handle_complete(message, meslen, finfo, hostidx); } else { log1(0, 0, "Received invalid message %s from %s", func_name(*func), destlist[hostidx].name); } break; } } return 1; }
/** * This is the main message reading loop. Messages are read, validated, * decrypted if necessary, then passed to the appropriate routine for handling. */ void mainloop() { struct uftp_h *header; unsigned char *buf, *decrypted, *message; int packetlen, listidx, hostidx, i; unsigned int decryptlen, meslen; uint8_t *func; struct sockaddr_in src; struct in_addr srcaddr; struct timeval *tv; const int bsize = 9000; // Roughly size of ethernet jumbo frame log0(0, 0, "%s", VERSIONSTR); for (i = 0; i < key_count; i++) { log(0, 0, "Loaded key with fingerprint %s", print_key_fingerprint(privkey[i])); } buf = calloc(bsize, 1); decrypted = calloc(bsize, 1); if ((buf == NULL) || (decrypted == NULL)) { syserror(0, 0, "calloc failed!"); exit(1); } header = (struct uftp_h *)buf; while (1) { tv = getrecenttimeout(); if (read_packet(listener, &src, buf, &packetlen, bsize, tv) <= 0) { continue; } if ((header->uftp_id != UFTP_VER_NUM) && (header->uftp_id != UFTP_3_0_VER)) { log(0, 0, "Invalid message from %s: not uftp packet " "or invalid version", inet_ntoa(src.sin_addr)); continue; } if (packetlen != sizeof(struct uftp_h) + ntohs(header->blsize)) { log(0, 0, "Invalid packet size from %s: got %d, expected %d", inet_ntoa(src.sin_addr), packetlen, sizeof(struct uftp_h) + ntohs(header->blsize)); continue; } if ((src.sin_addr.s_addr == out_addr.s_addr) && (src.sin_port == htons(port))) { // Packet from self -- drop continue; } if (header->func == HB_REQ) { handle_hb_request(&src, buf); continue; } if (header->func == HB_RESP) { handle_hb_response(listener, &src, buf, hb_hosts, hbhost_count, noname, privkey[0]); continue; } if (header->func == KEY_REQ) { handle_key_req(&src, buf); continue; } if (header->func == PROXY_KEY) { // Only clients handle these, so drop continue; } if ((proxy_type == SERVER_PROXY) && (down_addr.sin_addr.s_addr == INADDR_ANY)) { log(0, 0, "Rejecting message from %s: downstream address " "not established", inet_ntoa(src.sin_addr)); continue; } listidx = find_group(ntohl(header->group_id)); if (header->func == ANNOUNCE) { handle_announce(listidx, &src, buf); } else { if (listidx == -1) { continue; } if (proxy_type == SERVER_PROXY) { // Server proxies don't do anything outside of an ANNOUNCE. // Just send it on through. forward_message(listidx, &src, buf); continue; } if (header->func == ABORT) { handle_abort(listidx, &src, buf); continue; } if (!memcmp(&src, &group_list[listidx].up_addr, sizeof(src))) { // Downstream message if (header->func == KEYINFO) { handle_keyinfo(listidx, buf); } else if ((header->func == REG_CONF) && (group_list[listidx].keytype != KEY_NONE)) { handle_regconf(listidx, buf); } else { // If we don't need to process the message, don't bother // decrypting anything. Just forward it on. forward_message(listidx, &src, buf); } } else { // Upstream message // Decrypt first if necessary hostidx = find_client(listidx, header->srcaddr); if ((hostidx != -1) && (header->func == ENCRYPTED) && (group_list[listidx].keytype != KEY_NONE)) { if (!validate_and_decrypt(buf, &decrypted, &decryptlen, group_list[listidx].mtu,group_list[listidx].keytype, group_list[listidx].groupkey, group_list[listidx].groupsalt, group_list[listidx].ivlen, group_list[listidx].hashtype, group_list[listidx].grouphmackey, group_list[listidx].hmaclen, group_list[listidx].sigtype, group_list[listidx].destinfo[hostidx].pubkey, group_list[listidx].destinfo[hostidx].pubkeylen)) { log(ntohl(header->group_id), 0, "Rejecting message " "from %s: decrypt/validate failed", inet_ntoa(src.sin_addr)); continue; } func = (uint8_t *)decrypted; message = decrypted; meslen = decryptlen; } else { if ((hostidx != -1) && (group_list[listidx].keytype != KEY_NONE) && ((header->func == INFO_ACK) || (header->func == STATUS) || (header->func == COMPLETE))) { log(ntohl(header->group_id), 0, "Rejecting %s message " "from %s: not encrypted", func_name(header->func), inet_ntoa(src.sin_addr)); continue; } func = (uint8_t *)&header->func; message = buf + sizeof(struct uftp_h); meslen = ntohs(header->blsize); } if ((hostidx == -1) && (header->srcaddr == 0)) { srcaddr = src.sin_addr; } else { srcaddr.s_addr = header->srcaddr; } switch (*func) { case REGISTER: handle_register(listidx, hostidx, message, meslen, srcaddr.s_addr); break; case CLIENT_KEY: handle_clientkey(listidx, hostidx, message, meslen, srcaddr.s_addr); break; case INFO_ACK: handle_info_ack(listidx, hostidx, message, meslen); break; case STATUS: handle_status(listidx, hostidx, message, meslen); break; case COMPLETE: handle_complete(listidx, hostidx, message, meslen); break; default: forward_message(listidx, &src, buf); break; } } } } }