Esempio n. 1
0
/*
 * WRQ - receive a file from the client
 */
void
tftp_wrq(int peer, char *recvbuffer, ssize_t size)
{
	char *cp;
	int has_options = 0, ecode;
	char *filename, *mode;
	char fnbuf[PATH_MAX];

	cp = parse_header(peer, recvbuffer, size, &filename, &mode);
	size -= (cp - recvbuffer) + 1;

	strlcpy(fnbuf, filename, sizeof(fnbuf));
	reduce_path(fnbuf);
	filename = fnbuf;

	if (size > 0) {
		if (options_rfc_enabled)
			has_options = !parse_options(peer, cp, size);
		else
			tftp_log(LOG_INFO, "Options found but not enabled");
	}

	ecode = validate_access(peer, &filename, WRQ);
	if (ecode == 0) {
		if (has_options)
			send_oack(peer);
		else
			send_ack(peer, 0);
	}
	if (logging) {
		tftp_log(LOG_INFO, "%s: write request for %s: %s", peername,
			    filename, errtomsg(ecode));
	}

	if (ecode) {
		send_error(peer, ecode);
		exit(1);
	}
	tftp_recvfile(peer, mode);
	exit(0);
}
Esempio n. 2
0
/* Handle initial connection protocol  */
void tftp( Client *cl ) {
	struct tftphdr	*tp;
	char		*cp, *cp2, *ep;
	int		ecode;
	char		*mode;
	char		file[MAXPATHLEN];

	tp = cl->tp;
	tp->th_opcode = ntohs((u_short)tp->th_opcode);
	if (tp->th_opcode != RRQ) {
		// nak( cl, EBADOP );
		return;
	}

	errstr = NULL;
	cp = (char *)&tp->th_block;
	ep = (char *)cl->tp + cl->tpcc;

	if ( (ep - cp) > MAXPATHLEN ) {
		stats.badfilename++;
		nak( cl, EBADOP );
		return;
	}

	if ( *cp == '/' ) { cp++; }

	/* Extract filename */
	cp2 = file;
	while (cp < ep && *cp != '\0')
		*cp2++ = *cp++;
	if (cp >= ep) {
		++stats.badfilename;
		nak(cl, EBADOP);
		return;
	}
	*cp2 = '\0';
	++cp;

	/* Make sure mode is in packet */
	mode = cp;
	while (cp < ep && *cp != '\0') cp++;
	if (cp >= ep) {
		stats.badfilemode++;
		nak( cl, EBADOP );
		return;
	}

	if (strcasecmp(mode, "octet") != 0) {
		stats.badfilemode++;
		nak( cl, EBADOP );
		return;
	}

	ecode = validate_access( cl, file );
	if (ecode) {
		my_syslog( MLOG_TFTP, "%s %s \"%s\" DENIED (%s)",
			inet_ntoa(cl->sin.sin_addr),
			tp->th_opcode == WRQ ? "write" : "read",
			file,
			errstr != NULL ? errstr : errtomsg(ecode));
		cl->proc = CP_DONE;
		return;
	}

	if (cl->dynam == 0)
		my_TFTPlog( file, cl->sin.sin_addr.s_addr );
	/* my_syslog( MLOG_TFTP, "%s-%s req for \"%s\" from %s",
	    tp->th_opcode == WRQ ? "write" : "read",
	    mode, file, inet_ntoa(cl->sin.sin_addr));
	*/

	cl->state = ST_INIT;
	cl->tp = NULL;
	cl->tpcc = 0;
	cl->proc = CP_SENDFILE;
	// sendfile( cl );
}
Esempio n. 3
0
/*
 * RRQ - send a file to the client
 */
void
tftp_rrq(int peer, char *recvbuffer, ssize_t size)
{
	char *cp;
	int has_options = 0, ecode;
	char *filename, *mode;
	char	fnbuf[PATH_MAX];

	cp = parse_header(peer, recvbuffer, size, &filename, &mode);
	size -= (cp - recvbuffer) + 1;

	strcpy(fnbuf, filename);
	reduce_path(fnbuf);
	filename = fnbuf;

	if (size > 0) {
		if (options_rfc_enabled)
			has_options = !parse_options(peer, cp, size);
		else
			tftp_log(LOG_INFO, "Options found but not enabled");
	}

	ecode = validate_access(peer, &filename, RRQ);
	if (ecode == 0) {
		if (has_options) {
			int n;
			char lrecvbuffer[MAXPKTSIZE];
			struct tftphdr *rp = (struct tftphdr *)lrecvbuffer;

			send_oack(peer);
			n = receive_packet(peer, lrecvbuffer, MAXPKTSIZE,
				NULL, timeoutpacket);
			if (n < 0) {
				if (debug&DEBUG_SIMPLE)
					tftp_log(LOG_DEBUG, "Aborting: %s",
					    rp_strerror(n));
				return;
			}
			if (rp->th_opcode != ACK) {
				if (debug&DEBUG_SIMPLE)
					tftp_log(LOG_DEBUG,
					    "Expected ACK, got %s on OACK",
					    packettype(rp->th_opcode));
				return;
			}
		}
	}

	if (logging)
		tftp_log(LOG_INFO, "%s: read request for %s: %s", peername,
			    filename, errtomsg(ecode));

	if (ecode) {
		/*
		 * Avoid storms of naks to a RRQ broadcast for a relative
		 * bootfile pathname from a diskless Sun.
		 */
		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
			exit(0);
		send_error(peer, ecode);
		exit(1);
	}
	tftp_xmitfile(peer, mode);
}
Esempio n. 4
0
/*
 * Handle initial connection protocol.
 */
void
tftp(struct tftphdr *tp, int size)
{
	char *cp;
	size_t i;
	int first = 1, has_options = 0, ecode;
	struct formats *pf;
	char *filename, *mode = NULL, *option, *ccp;
	char fnbuf[MAXPATHLEN];

	cp = tp->th_stuff;
again:
	while (cp < buf + size) {
		if (*cp == '\0')
			break;
		cp++;
	}
	if (*cp != '\0') {
		nak(EBADOP);
		exit(1);
	}
	i = cp - tp->th_stuff;
	if (i >= sizeof(fnbuf)) {
		nak(EBADOP);
		exit(1);
	}
	memcpy(fnbuf, tp->th_stuff, i);
	fnbuf[i] = '\0';
	filename = fnbuf;
	if (first) {
		mode = ++cp;
		first = 0;
		goto again;
	}
	for (cp = mode; *cp; cp++)
		if (isupper(*cp))
			*cp = tolower(*cp);
	for (pf = formats; pf->f_mode; pf++)
		if (strcmp(pf->f_mode, mode) == 0)
			break;
	if (pf->f_mode == NULL) {
		nak(EBADOP);
		exit(1);
	}
	while (++cp < buf + size) {
		for (i = 2, ccp = cp; i > 0; ccp++) {
			if (ccp >= buf + size) {
				/*
				 * Don't reject the request, just stop trying
				 * to parse the option and get on with it.
				 * Some Apple OpenFirmware versions have
				 * trailing garbage on the end of otherwise
				 * valid requests.
				 */
				goto option_fail;
			} else if (*ccp == '\0')
				i--;
		}
		for (option = cp; *cp; cp++)
			if (isupper(*cp))
				*cp = tolower(*cp);
		for (i = 0; options[i].o_type != NULL; i++)
			if (strcmp(option, options[i].o_type) == 0) {
				options[i].o_request = ++cp;
				has_options = 1;
			}
		cp = ccp-1;
	}

option_fail:
	if (options[OPT_TIMEOUT].o_request) {
		int to = atoi(options[OPT_TIMEOUT].o_request);
		if (to < 1 || to > 255) {
			nak(EBADOP);
			exit(1);
		}
		else if (to <= max_rexmtval)
			options[OPT_TIMEOUT].o_reply = rexmtval = to;
		else
			options[OPT_TIMEOUT].o_request = NULL;
	}

	ecode = (*pf->f_validate)(&filename, tp->th_opcode);
	if (has_options)
		oack();
	if (logging) {
		char hbuf[NI_MAXHOST];

		getnameinfo((struct sockaddr *)&from, from.ss_len,
			    hbuf, sizeof(hbuf), NULL, 0, 
			    NI_WITHSCOPEID);
		syslog(LOG_INFO, "%s: %s request for %s: %s", hbuf,
			tp->th_opcode == WRQ ? "write" : "read",
			filename, errtomsg(ecode));
	}
	if (ecode) {
		/*
		 * Avoid storms of naks to a RRQ broadcast for a relative
		 * bootfile pathname from a diskless Sun.
		 */
		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
			exit(0);
		nak(ecode);
		exit(1);
	}
	if (tp->th_opcode == WRQ)
		(*pf->f_recv)(pf);
	else
		(*pf->f_send)(pf);
	exit(0);
}
Esempio n. 5
0
File: tftpd.c Progetto: 274914765/C
/*
 * Handle initial connection protocol.
 */
void tftp (struct tftphdr *tp, int size)
{
    register char *cp;

    int first = 1, ecode;

    register struct formats *pf;

    char *filename, *mode;

    filename = cp = tp->th_stuff;
  again:
    while (cp < buf + size)
    {
        if (*cp == '\0')
            break;
        cp++;
    }
    if (*cp != '\0')
    {
        nak (EBADOP);
        exit (1);
    }
    if (first)
    {
        mode = ++cp;
        first = 0;
        goto again;
    }
    for (cp = mode; *cp; cp++)
        if (isupper (*cp))
            *cp = tolower (*cp);
    for (pf = formats; pf->f_mode; pf++)
        if (strcmp (pf->f_mode, mode) == 0)
            break;
    if (pf->f_mode == 0)
    {
        nak (EBADOP);
        exit (1);
    }
    ecode = (*pf->f_validate) (&filename, tp->th_opcode);
    if (logging)
    {
        syslog (LOG_INFO, "%s: %s request for %s: %s",
                verifyhost (&from), tp->th_opcode == WRQ ? "write" : "read", filename, errtomsg (ecode));
    }
    if (ecode)
    {
        /*
         * Avoid storms of naks to a RRQ broadcast for a relative
         * bootfile pathname from a diskless Sun.
         */
        if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
            exit (0);
        nak (ecode);
        exit (1);
    }
    if (tp->th_opcode == WRQ)
        (*pf->f_recv) (pf);
    else
        (*pf->f_send) (pf);
    exit (0);
}