Exemplo n.º 1
0
/**
 * 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;
    struct uftp2_h *v2_header;
    unsigned char *buf, *decrypted, *message;
    unsigned int decryptlen, meslen, expectedlen;
    int packetlen, listidx, i;
    uint8_t version, *func;
    uint32_t v2func;
    struct sockaddr_in src;
    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++) {
        log1(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;
    v2_header = (struct uftp2_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)) {
            version = header->uftp_id;
            expectedlen = sizeof(struct uftp_h) + ntohs(header->blsize);
            listidx = find_file(ntohl(header->group_id));
        } else if (ntohl(v2_header->uftp_id) == V2_UFTP_ID) {
            version = UFTP_V2_VER;
            expectedlen = V2_PACKETSIZE;
            listidx = find_file(ntohl(v2_header->tx_id));
            v2func = ntohl(v2_header->func);
        } else {
            log(0, 0, "Invalid message from %s: not uftp packet "
                      "or invalid version", inet_ntoa(src.sin_addr));
            continue;
        }
        if (packetlen != expectedlen) {
            log(0, 0, "Invalid packet size from %s: got %d, expected %d",
                      inet_ntoa(src.sin_addr), packetlen, expectedlen);
            continue;
        }

        if (((version == UFTP_VER_NUM) || (version == UFTP_3_0_VER)) &&
                (header->func == ENCRYPTED) && (listidx != -1) &&
                (group_list[listidx].keytype != KEY_NONE)) {
            if (group_list[listidx].phase == PHASE_REGISTERED) {
                log(ntohl(header->group_id), 0, "Got encrypted packet from %s "
                        "but keys not established", inet_ntoa(src.sin_addr));
            }

            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].serverkey,
                    group_list[listidx].server_keylen)) {
                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 ((version == UFTP_VER_NUM) || (version == UFTP_3_0_VER)) {
            if ((listidx != -1) && (group_list[listidx].keytype != KEY_NONE) &&
                    ((header->func == FILEINFO) || (header->func == FILESEG) ||
                     (header->func == DONE) || (header->func == DONE_CONF) ||
                     ((header->func == ABORT) &&
                         (group_list[listidx].phase != PHASE_REGISTERED)))) {
                log(0, 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);
        } else {
            // Version 2
            message = buf;
            meslen = V2_PACKETSIZE;
        }

        if (((version == UFTP_VER_NUM) || (version == UFTP_3_0_VER)) &&
                (header->func == PROXY_KEY)) {
            handle_proxy_key(&src, buf);
            continue;
        }
        if (((version == UFTP_VER_NUM) || (version == UFTP_3_0_VER)) &&
                (header->func == HB_RESP)) {
            handle_hb_response(listener, &src, buf, hb_hosts, hbhost_count,
                               noname, privkey[0]);
            continue;
        }
        if ((((version == UFTP_VER_NUM) || (version == UFTP_3_0_VER)) &&
                 (header->func == ANNOUNCE)) ||
                ((version == UFTP_V2_VER) && (v2func == V2_ANNOUNCE))) {
            // Ignore any ANNOUNCE for a group we're already handling
            if (listidx == -1) {
                handle_announce(src, version, buf);
            } else if (group_list[listidx].phase == PHASE_MIDGROUP) {
                // Make sure we don't time out while waiting for other
                // clients to register with the server.
                set_timeout(listidx);
            }
        } else {
            if (listidx == -1) {
                // group / file ID not in list
                continue;
            }
            if (group_list[listidx].version != version) {
                log(group_list[listidx].group_id, group_list[listidx].file_id,
                        "Version mismatch");
                continue;
            }
            if ((((version == UFTP_VER_NUM) || (version == UFTP_3_0_VER)) &&
                     (*func == ABORT)) ||
                    ((version == UFTP_V2_VER) && (v2func == V2_ABORT))) {
                handle_abort(listidx, message, meslen);
                continue;
            }
            switch (group_list[listidx].phase) {
            case PHASE_REGISTERED:
                if (version == UFTP_V2_VER) {
                    // This is repeated in one of the cases below, but it's
                    // separated out anyway to keep the V2 stuff separate.
                    handle_regconf(listidx, message, meslen);
                } else if (group_list[listidx].keytype != KEY_NONE) {
                    if (*func == KEYINFO) {
                        handle_keyinfo(listidx, buf);
                    } else {
                        log(group_list[listidx].group_id,
                                group_list[listidx].file_id,
                                "Expected KEYINFO, got %s", func_name(*func));
                    }
                } else if (group_list[listidx].keytype == KEY_NONE) {
                    if (*func == REG_CONF) {
                        handle_regconf(listidx, message, meslen);
                    } else if (*func == FILEINFO) {
                        handle_fileinfo(listidx, message, meslen);
                    } else {
                        log(group_list[listidx].group_id,
                                group_list[listidx].file_id,
                                "Expected REG_CONF, got %s", func_name(*func));
                    }
                }
                break;
            case PHASE_MIDGROUP:
                if (((version == UFTP_VER_NUM) || (version == UFTP_3_0_VER)) &&
                        (*func == FILEINFO)) {
                    handle_fileinfo(listidx, message, meslen);
                } else if (((version == UFTP_VER_NUM) ||
                            (version == UFTP_3_0_VER)) && (*func == KEYINFO)) {
                    handle_keyinfo(listidx, buf);
                } else if (((version == UFTP_V2_VER) && (v2func == V2_DONE)) ||
                        (((version == UFTP_VER_NUM) ||
                          (version == UFTP_3_0_VER)) && (*func == DONE))) {
                    handle_done(listidx, message, meslen);
                } else {
                    // Other clients may be still getting earlier files or
                    // setting up, so silently ignore anything unexpected
                    // and reset the timeout.
                    set_timeout(listidx);
                }
                break;
            case PHASE_RECEIVING:
                if (((version == UFTP_VER_NUM) || (version == UFTP_3_0_VER)) &&
                        (*func == FILEINFO)) {
                    handle_fileinfo(listidx, message, meslen);
                } else if (((version == UFTP_V2_VER) &&
                            (v2func == V2_FILESEG)) ||
                        (((version == UFTP_VER_NUM) ||
                          (version == UFTP_3_0_VER)) && (*func == FILESEG))) {
                    handle_fileseg(listidx, message, meslen);
                } else if (((version == UFTP_V2_VER) && (v2func == V2_DONE)) ||
                        (((version == UFTP_VER_NUM) ||
                          (version == UFTP_3_0_VER)) && (*func == DONE))) {
                    handle_done(listidx, message, meslen);
                }
                break;
            case PHASE_COMPLETE:
                if (((version == UFTP_V2_VER) && (v2func == V2_DONE_CONF)) ||
                        (((version == UFTP_VER_NUM) || 
                          (version == UFTP_3_0_VER)) && (*func == DONE_CONF))) {
                    handle_done_conf(listidx, message, meslen);
                }
                break;
            }
        }
    }
}
Exemplo n.º 2
0
/**
 * This is the main message reading loop.  Messages are read, validated,
 * decrypted if necessary, then passed to the appropriate routine for handling.
 */
void mainloop(void)
{
    struct uftp_h *header;
    struct group_list_t *group;
    unsigned char *buf, *decrypted, *message;
    char rxname[INET6_ADDRSTRLEN];
    unsigned int decryptlen, meslen;
    int packetlen, rval, i, ecn;
    uint8_t version, *func, tos;
    uint16_t txseq;
    union sockaddr_u src;
    struct timeval *tv, rxtime;
    double new_grtt;

    log2(0, 0, 0, "%s", VERSIONSTR);
    for (i = 0; i < key_count; i++) {
        if (privkey_type[i] == KEYBLOB_RSA) {
            log2(0, 0, 0, "Loaded %d bit RSA key with fingerprint %s",
                  RSA_keylen(privkey[i].rsa) * 8,
                  print_key_fingerprint(privkey[i], KEYBLOB_RSA));
        } else {
            log2(0, 0, 0, "Loaded ECDSA key with curve %s and fingerprint %s",
                  curve_name(get_EC_curve(privkey[i].ec)),
                  print_key_fingerprint(privkey[i], KEYBLOB_EC));
        }
    }

    buf = safe_calloc(MAXMTU, 1);
    decrypted = safe_calloc(MAXMTU, 1);
    header = (struct uftp_h *)buf;

    while (1) {
        tv = getrecenttimeout();
        if (tv) {
            log5(0, 0, 0, "read timeout: %d.%06d", tv->tv_sec, tv->tv_usec);
        }
        if (read_packet(listener, &src, buf, &packetlen,
                        MAXMTU, tv, &tos) <= 0) {
            continue;
        }
        gettimeofday(&rxtime, NULL);

        if ((rval = getnameinfo((struct sockaddr *)&src, family_len(src),
                rxname, sizeof(rxname), NULL, 0, NI_NUMERICHOST)) != 0) {
            log1(0, 0, 0, "getnameinfo failed: %s", gai_strerror(rval));
        }

        if (header->version == UFTP_VER_NUM) {
            version = header->version;
            group = find_group(ntohl(header->group_id), header->group_inst);
        } else {
            log1(0, 0, 0, "Invalid message from %s: not uftp packet "
                          "or invalid version", rxname);
            continue;
        }
        if (packetlen < sizeof(struct uftp_h) + 4) {
            log1(0, 0, 0, "Invalid packet size from %s: %d", rxname, packetlen);
            continue;
        }

        txseq = htons(header->seq);
        // A KEY_INFO or ABORT could come from a proxy, so don't check the seq
        // TODO: need to account for these in the loss history
        if ((group != NULL) && (header->func != KEYINFO) &&
                (header->func != ABORT)) {
            if ((int16_t)(group->max_txseq - txseq) > MAXMISORDER) {
                glog3(group, "seq out of range, dropping");
                continue;
            }
            if (group->cc_type != CC_NONE) {
                ecn = ((tos & 0x3) == 3);
                update_loss_history(group, txseq, packetlen, ecn);
            } else if ((int16_t)(txseq - group->max_txseq) > 0) {
                group->max_txseq = txseq;
            }
        }

        if ((header->func == ENCRYPTED) && (group != NULL) &&
                (group->keytype != KEY_NONE)) {
            if (group->phase == PHASE_REGISTERED) {
                glog1(group, "Got encrypted packet from %s "
                             "but keys not established", rxname);
            }

            if (!validate_and_decrypt(buf, packetlen, &decrypted, &decryptlen,
                    group->keytype, group->groupkey, group->groupsalt,
                    group->ivlen, group->hashtype, group->grouphmackey,
                    group->hmaclen, group->sigtype, group->keyextype,
                    group->server_pubkey, group->server_pubkeylen)) {
                glog1(group, "Rejecting message from %s: "
                             "decrypt/validate failed", rxname);
                continue;
            }
            func = (uint8_t *)decrypted;
            message = decrypted;
            meslen = decryptlen;
        } else {
            if ((group != NULL) && (group->keytype != KEY_NONE) &&
                    ((header->func == FILEINFO) || (header->func == FILESEG) ||
                     (header->func == DONE) || (header->func == DONE_CONF) ||
                     ((header->func == ABORT) &&
                         (group->phase != PHASE_REGISTERED)))) {
                glog1(group, "Rejecting %s message from %s: not encrypted",
                             func_name(header->func), rxname);
                continue;
            }
            func = (uint8_t *)&header->func;
            message = buf + sizeof(struct uftp_h);
            meslen = packetlen - sizeof(struct uftp_h);
        }

        if (group != NULL) {
            new_grtt = unquantize_grtt(header->grtt);
            if (fabs(new_grtt - group->grtt) > 0.001) {
                group->grtt = new_grtt;
                set_timeout(group, 1);
            }
            group->gsize = unquantize_gsize(header->gsize);
            glog5(group, "grtt: %.3f", group->grtt);
        }

        if (header->func == PROXY_KEY) {
            handle_proxy_key(&src, message, meslen);
            continue;
        }
        if (header->func == HB_RESP) {
            handle_hb_response(listener, &src, message, meslen, hb_hosts,
                               hbhost_count, privkey[0], privkey_type[0], uid);
            continue;
        }
        if (header->func == ANNOUNCE) {
            // Ignore any ANNOUNCE for a group we're already handling
            if (group == NULL) {
                handle_announce(&src, buf, packetlen, rxtime);
            } else if (group->phase == PHASE_MIDGROUP) {
                // Make sure we don't time out while waiting for other
                // clients to register with the server.
                set_timeout(group, 0);
            }
        } else {
            if (group == NULL) {
                // group / file ID not in list
                continue;
            }
            if (group->version != version) {
                glog1(group, "Version mismatch");
                continue;
            }
            if (group->src_id != header->src_id) {
                glog1(group, "Source ID mismatch");
                continue;
            }
            if (*func == ABORT) {
                handle_abort(group, message, meslen);
                continue;
            }
            switch (group->phase) {
            case PHASE_REGISTERED:
                if (group->keytype != KEY_NONE) {
                    if (*func == KEYINFO) {
                        handle_keyinfo(group, message, meslen, header->src_id);
                    } else {
                        glog1(group, "Expected KEYINFO, got %s",
                                     func_name(*func));
                    }
                } else if (group->keytype == KEY_NONE) {
                    if (*func == REG_CONF) {
                        handle_regconf(group, message, meslen);
                    } else if (*func == FILEINFO) {
                        handle_fileinfo(group, message, meslen, rxtime);
                    } else {
                        glog1(group, "Expected REG_CONF, got %s",
                                     func_name(*func));
                    }
                }
                break;
            case PHASE_MIDGROUP:
                if (*func == FILEINFO) {
                    handle_fileinfo(group, message, meslen, rxtime);
                } else if (*func == KEYINFO) {
                    handle_keyinfo(group, message, meslen, header->src_id);
                } else if (*func == DONE) {
                    handle_done(group, message, meslen);
                } else {
                    // Other clients may be still getting earlier files or
                    // setting up, so silently ignore anything unexpected
                    // and reset the timeout.
                    set_timeout(group, 0);
                }
                break;
            case PHASE_RECEIVING:
                if (*func == FILEINFO) {
                    handle_fileinfo(group, message, meslen, rxtime);
                } else if (*func == FILESEG) {
                    handle_fileseg(group, message, meslen, txseq);
                } else if (*func == DONE) {
                    handle_done(group, message, meslen);
                } else if (*func == CONG_CTRL) {
                    handle_cong_ctrl(group, message, meslen, rxtime);
                }
                break;
            case PHASE_COMPLETE:
                if (*func == DONE_CONF) {
                    handle_done_conf(group, message, meslen);
                }
                break;
            }
        }
    }
}
Exemplo n.º 3
0
/*
  isdnhdlc_decode - decodes HDLC frames from a transparent bit stream.

  The source buffer is scanned for valid HDLC frames looking for
  flags (01111110) to indicate the start of a frame. If the start of
  the frame is found, the bit stuffing is removed (0 after 5 1's).
  When a new flag is found, the complete frame has been received
  and the CRC is checked.
  If a valid frame is found, the function returns the frame length
  excluding the CRC with the bit HDLC_END_OF_FRAME set.
  If the beginning of a valid frame is found, the function returns
  the length.
  If a framing error is found (too many 1s and not a flag) the function
  returns the length with the bit HDLC_FRAMING_ERROR set.
  If a CRC error is found the function returns the length with the
  bit HDLC_CRC_ERROR set.
  If the frame length exceeds the destination buffer size, the function
  returns the length with the bit HDLC_LENGTH_ERROR set.

  src - source buffer
  slen - source buffer length
  count - number of bytes removed (decoded) from the source buffer
  dst _ destination buffer
  dsize - destination buffer size
  returns - number of decoded bytes in the destination buffer and status
  flag.
*/
int isdnhdlc_decode(struct isdnhdlc_vars *hdlc, const u8 *src, int slen,
		    int *count, u8 *dst, int dsize)
{
	int status = 0;

	static const unsigned char fast_flag[] = {
		0x00, 0x00, 0x00, 0x20, 0x30, 0x38, 0x3c, 0x3e, 0x3f
	};

	static const unsigned char fast_flag_value[] = {
		0x00, 0x7e, 0xfc, 0xf9, 0xf3, 0xe7, 0xcf, 0x9f, 0x3f
	};

	static const unsigned char fast_abort[] = {
		0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
	};

#define handle_fast_flag(h)						\
	do {								\
		if (h->cbin == fast_flag[h->bit_shift]) {		\
			h->ffvalue = fast_flag_value[h->bit_shift];	\
			h->state = HDLC_FAST_FLAG;			\
			h->ffbit_shift = h->bit_shift;			\
			h->bit_shift = 1;				\
		} else {						\
			h->state = HDLC_GET_DATA;			\
			h->data_received = 0;				\
		}							\
	} while (0)

#define handle_abort(h)						\
	do {							\
		h->shift_reg = fast_abort[h->ffbit_shift - 1];	\
		h->hdlc_bits1 = h->ffbit_shift - 2;		\
		if (h->hdlc_bits1 < 0)				\
			h->hdlc_bits1 = 0;			\
		h->data_bits = h->ffbit_shift - 1;		\
		h->state = HDLC_GET_DATA;			\
		h->data_received = 0;				\
	} while (0)

	*count = slen;

	while (slen > 0) {
		if (hdlc->bit_shift == 0) {
			/* the code is for bitreverse streams */
			if (hdlc->do_bitreverse == 0)
				hdlc->cbin = bitrev8(*src++);
			else
				hdlc->cbin = *src++;
			slen--;
			hdlc->bit_shift = 8;
			if (hdlc->do_adapt56)
				hdlc->bit_shift--;
		}

		switch (hdlc->state) {
		case STOPPED:
			return 0;
		case HDLC_FAST_IDLE:
			if (hdlc->cbin == 0xff) {
				hdlc->bit_shift = 0;
				break;
			}
			hdlc->state = HDLC_GET_FLAG_B0;
			hdlc->hdlc_bits1 = 0;
			hdlc->bit_shift = 8;
			break;
		case HDLC_GET_FLAG_B0:
			if (!(hdlc->cbin & 0x80)) {
				hdlc->state = HDLC_GETFLAG_B1A6;
				hdlc->hdlc_bits1 = 0;
			} else {
				if ((!hdlc->do_adapt56) &&
				    (++hdlc->hdlc_bits1 >= 8) &&
				    (hdlc->bit_shift == 1))
					hdlc->state = HDLC_FAST_IDLE;
			}
			hdlc->cbin <<= 1;
			hdlc->bit_shift--;
			break;
		case HDLC_GETFLAG_B1A6:
			if (hdlc->cbin & 0x80) {
				hdlc->hdlc_bits1++;
				if (hdlc->hdlc_bits1 == 6)
					hdlc->state = HDLC_GETFLAG_B7;
			} else
				hdlc->hdlc_bits1 = 0;
			hdlc->cbin <<= 1;
			hdlc->bit_shift--;
			break;
		case HDLC_GETFLAG_B7:
			if (hdlc->cbin & 0x80) {
				hdlc->state = HDLC_GET_FLAG_B0;
			} else {
				hdlc->state = HDLC_GET_DATA;
				hdlc->crc = 0xffff;
				hdlc->shift_reg = 0;
				hdlc->hdlc_bits1 = 0;
				hdlc->data_bits = 0;
				hdlc->data_received = 0;
			}
			hdlc->cbin <<= 1;
			hdlc->bit_shift--;
			break;
		case HDLC_GET_DATA:
			if (hdlc->cbin & 0x80) {
				hdlc->hdlc_bits1++;
				switch (hdlc->hdlc_bits1) {
				case 6:
					break;
				case 7:
					if (hdlc->data_received)
						/* bad frame */
						status = -HDLC_FRAMING_ERROR;
					if (!hdlc->do_adapt56) {
						if (hdlc->cbin == fast_abort
						    [hdlc->bit_shift + 1]) {
							hdlc->state =
								HDLC_FAST_IDLE;
							hdlc->bit_shift = 1;
							break;
						}
					} else
						hdlc->state = HDLC_GET_FLAG_B0;
					break;
				default:
					hdlc->shift_reg >>= 1;
					hdlc->shift_reg |= 0x80;
					hdlc->data_bits++;
					break;
				}
			} else {
				switch (hdlc->hdlc_bits1) {
				case 5:
					break;
				case 6:
					if (hdlc->data_received)
						status = check_frame(hdlc);
					hdlc->crc = 0xffff;
					hdlc->shift_reg = 0;
					hdlc->data_bits = 0;
					if (!hdlc->do_adapt56)
						handle_fast_flag(hdlc);
					else {
						hdlc->state = HDLC_GET_DATA;
						hdlc->data_received = 0;
					}
					break;
				default:
					hdlc->shift_reg >>= 1;
					hdlc->data_bits++;
					break;
				}
				hdlc->hdlc_bits1 = 0;
			}
			if (status) {
				hdlc->dstpos = 0;
				*count -= slen;
				hdlc->cbin <<= 1;
				hdlc->bit_shift--;
				return status;
			}
			if (hdlc->data_bits == 8) {
				hdlc->data_bits = 0;
				hdlc->data_received = 1;
				hdlc->crc = crc_ccitt_byte(hdlc->crc,
							   hdlc->shift_reg);

				/* good byte received */
				if (hdlc->dstpos < dsize)
					dst[hdlc->dstpos++] = hdlc->shift_reg;
				else {
					/* frame too long */
					status = -HDLC_LENGTH_ERROR;
					hdlc->dstpos = 0;
				}
			}
			hdlc->cbin <<= 1;
			hdlc->bit_shift--;
			break;
		case HDLC_FAST_FLAG:
			if (hdlc->cbin == hdlc->ffvalue) {
				hdlc->bit_shift = 0;
				break;
			} else {
				if (hdlc->cbin == 0xff) {
					hdlc->state = HDLC_FAST_IDLE;
					hdlc->bit_shift = 0;
				} else if (hdlc->ffbit_shift == 8) {
					hdlc->state = HDLC_GETFLAG_B7;
					break;
				} else
					handle_abort(hdlc);
			}
			break;
		default:
			break;
		}
Exemplo n.º 4
0
static apr_status_t ftp_protocol_loop(struct lfd_sess * sess)
{
	apr_status_t	  rc = APR_SUCCESS;
	int 		  rnfrto; // "rename from" and "rename to" should go togheter
	char		* temp_name;

	temp_name = NULL;
	rnfrto = 0;
	while(APR_SUCCESS == rc)
	{
		apr_pool_clear(sess->loop_pool);
		rc = lfd_cmdio_get_cmd_and_arg(sess, &sess->ftp_cmd_str, &sess->ftp_arg_str);
		if(APR_SUCCESS != rc)
			return rc;
		// special case
		if(lfd_cmdio_cmd_equals(sess, "RNTO"))
		{
			if(rnfrto)
			{
				rnfrto = 0;
				rc = handle_rnto(sess, temp_name);
			}
			else
				rc = handle_bad_rnto(sess);
			continue;
		}
		// here we treat all the other cases
		if(rnfrto){
			rnfrto = 0;
			rc = handle_bad_rnto(sess);
			continue;
		}

		if(lfd_cmdio_cmd_equals(sess, "PASV"))
		{
			rc = handle_pasv(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "SYST"))
		{
			rc = handle_syst(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "USER"))
		{
			rc = handle_user(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "PASS"))
		{
			rc = handle_pass(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "QUIT"))
		{
			rc = handle_quit(sess);
			return rc;
		}
		else if(lfd_cmdio_cmd_equals(sess, "ABOR"))
		{
			rc = handle_abort(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "PORT"))
		{
			rc = handle_port(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "RMD"))
		{
			rc = handle_dir_remove(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "MKD"))
		{
			rc = handle_dir_create(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "PWD"))
		{
			rc = handle_pwd(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "CWD"))
		{
			rc = handle_cwd(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "CDUP"))
		{
			rc = handle_cdup(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "RNFR"))
		{
			rc = handle_rnfr(sess, &temp_name);
			if(APR_SUCCESS == rc && NULL != temp_name)
				rnfrto = 1;
		}
		else if(lfd_cmdio_cmd_equals(sess, "TYPE"))
		{
			rc = handle_type(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "RETR"))
		{
			rc = handle_retr(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "STOR"))
		{
			rc = handle_stor(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "DELE"))
		{
			rc = handle_dele(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "STOU"))
		{
			rc = handle_stou(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "LIST"))
		{
			rc = handle_list(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "FEAT"))
		{
			rc = handle_feat(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "APPE"))
		{
			rc = handle_appe(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "SITE"))
		{
			rc = handle_site(sess);
		}
		else if(lfd_cmdio_cmd_equals(sess, "ALLO"))
		{
			rc = lfd_cmdio_write(sess, FTP_ALLOOK, "ALLO command ignored.");
		}
		else if(lfd_cmdio_cmd_equals(sess, "REIN"))
		{
			rc = lfd_cmdio_write(sess, FTP_COMMANDNOTIMPL, "REIN not implemented.");
		}
		else if(lfd_cmdio_cmd_equals(sess, "ACCT"))
		{
			rc = lfd_cmdio_write(sess, FTP_COMMANDNOTIMPL, "ACCT not implemented.");
		}
		else if(lfd_cmdio_cmd_equals(sess, "SMNT"))
		{
			rc = lfd_cmdio_write(sess, FTP_COMMANDNOTIMPL, "SMNT not implemented.");
		}
		else //default
		{
			printf("The cmd [%s] has no installed handler! \n", sess->ftp_cmd_str);
			if(NULL != sess->ftp_arg_str)
				printf("The cmd args were [%s] \n", sess->ftp_arg_str);
			lfd_cmdio_write(sess, FTP_COMMANDNOTIMPL, "Command not implemented.");
		}
	}
	return rc;
}
Exemplo n.º 5
0
/**
 * 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;
}
Exemplo n.º 6
0
/**
 * 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;
}
Exemplo n.º 7
0
/**
 * 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;
                }
            }
        }
    }
}