Ejemplo n.º 1
0
/*
 * Handle initial connection protocol.
 */
static int tftp(struct testcase *test, struct tftphdr *tp, int size)
{
  char *cp;
  int first = 1, ecode;
  struct formats *pf;
  char *filename, *mode = NULL;

  /* store input protocol */
  fprintf(test->server, "opcode: %x\n", tp->th_opcode);

  cp = (char *)&tp->th_stuff;
  filename = cp;
again:
  while (cp < buf + size) {
    if (*cp == '\0')
      break;
    cp++;
  }
  if (*cp) {
    nak(EBADOP);
    return 3;
  }
  if (first) {
    mode = ++cp;
    first = 0;
    goto again;
  }
  /* store input protocol */
  fprintf(test->server, "filename: %s\n", filename);

  for (cp = mode; *cp; cp++)
    if (isupper((int)*cp))
      *cp = tolower((int)*cp);

  /* store input protocol */
  fprintf(test->server, "mode: %s\n", mode);

  for (pf = formats; pf->f_mode; pf++)
    if (strcmp(pf->f_mode, mode) == 0)
      break;
  if (!pf->f_mode) {
    nak(EBADOP);
    return 2;
  }
  ecode = validate_access(test, filename, tp->th_opcode);
  if (ecode) {
    nak(ecode);
    return 1;
  }
  if (tp->th_opcode == WRQ)
    recvtftp(test, pf);
  else
    sendtftp(test, pf);

  return 0;
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
/*
 * Handle initial connection protocol.
 */
static int tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
{
  char *cp;
  int first = 1, ecode;
  struct formats *pf;
  char *filename, *mode = NULL;
  int error;
  FILE *server;

  /* Open request dump file. */
  server = fopen(REQUEST_DUMP, "ab");
  if(!server) {
    error = ERRNO;
    logmsg("fopen() failed with error: %d %s", error, strerror(error));
    logmsg("Error opening file: %s", REQUEST_DUMP);
    return -1;
  }

  /* store input protocol */
  fprintf(server, "opcode: %x\n", tp->th_opcode);

  cp = (char *)&tp->th_stuff;
  filename = cp;
again:
  while (cp < buf + size) {
    if (*cp == '\0')
      break;
    cp++;
  }
  if (*cp) {
    nak(EBADOP);
    fclose(server);
    return 3;
  }
  if (first) {
    mode = ++cp;
    first = 0;
    goto again;
  }
  /* store input protocol */
  fprintf(server, "filename: %s\n", filename);

  for (cp = mode; cp && *cp; cp++)
    if(ISUPPER(*cp))
      *cp = (char)tolower((int)*cp);

  /* store input protocol */
  fprintf(server, "mode: %s\n", mode);
  fclose(server);

  for (pf = formata; pf->f_mode; pf++)
    if (strcmp(pf->f_mode, mode) == 0)
      break;
  if (!pf->f_mode) {
    nak(EBADOP);
    return 2;
  }
  ecode = validate_access(test, filename, tp->th_opcode);
  if (ecode) {
    nak(ecode);
    return 1;
  }
  if (tp->th_opcode == opcode_WRQ)
    recvtftp(test, pf);
  else
    sendtftp(test, pf);

  return 0;
}
Ejemplo n.º 4
0
Archivo: relay.c Proyecto: csmuc/iProxy
int serv_loop()
{
  int    cs, ss = 0;
  struct sockaddr_storage cl;
  fd_set readable;
  int    i, n, len;
  char   cl_addr[NI_MAXHOST];
  char   cl_name[NI_MAXHOST];
  int    error;
  pid_t  pid;

#ifdef USE_THREAD
  if (threading) {
    blocksignal(SIGHUP);
    blocksignal(SIGINT);
    blocksignal(SIGUSR1);
  }
#endif

  for (;;) {
    readable = allsock;

    MUTEX_LOCK(mutex_select);
    n = select(maxsock+1, &readable, 0, 0, 0);
    if (n <= 0) {
      if (n < 0 && errno != EINTR) {
        msg_out(warn, "select: %m");
      }
      MUTEX_UNLOCK(mutex_select);
      continue;
    }

#ifdef USE_THREAD
    if ( ! threading ) {
#endif
      /* handle any queued signal flags */
      if (FD_ISSET(sig_queue[0], &readable)) {
        if (ioctl(sig_queue[0], FIONREAD, &i) != 0) {
          msg_out(crit, "ioctl: %m");
          exit(-1);
        }
        while (--i >= 0) {
          char c;
          if (read(sig_queue[0], &c, 1) != 1) {
            msg_out(crit, "read: %m");
            exit(-1);
          }
          switch(c) {
          case 'H': /* sighup */
            reload();
            break;
          case 'C': /* sigchld */
            reapchild();
            break;
          case 'T': /* sigterm */
            cleanup();
            break;
          default:
            break;
          }
        }
      }
#ifdef USE_THREAD
    }
#endif

    for ( i = 0; i < serv_sock_ind; i++ ) {
      if (FD_ISSET(serv_sock[i], &readable)) {
	n--;
	break;
      }
    }
    if ( n < 0 || i >= serv_sock_ind ) {
      MUTEX_UNLOCK(mutex_select);
      continue;
    }

    len = sizeof(struct sockaddr_storage);
    cs = accept(serv_sock[i], (struct sockaddr *)&cl, (socklen_t *)&len);
    if (cs < 0) {
      if (errno == EINTR
#ifdef SOLARIS
	  || errno == EPROTO
#endif
	  || errno == EWOULDBLOCK
	  || errno == ECONNABORTED) {
	; /* ignore */
      } else {
	/* real accept error */
	msg_out(warn, "accept: %m");
      }
      MUTEX_UNLOCK(mutex_select);
      continue;
    }
    MUTEX_UNLOCK(mutex_select);

#ifdef USE_THREAD
    if ( !threading ) {
#endif
      if (max_child > 0 && cur_child >= max_child) {
	msg_out(warn, "child: cur %d; exeedeing max(%d)",
		          cur_child, max_child);
	close(cs);
	continue;
      }
#ifdef USE_THREAD
    }
#endif

    error = getnameinfo((struct sockaddr *)&cl, len,
			cl_addr, sizeof(cl_addr),
			NULL, 0,
			NI_NUMERICHOST);
    if (resolv_client) {
      error = getnameinfo((struct sockaddr *)&cl, len,
			  cl_name, sizeof(cl_name),
			  NULL, 0, 0);
      msg_out(norm, "%s[%s] connected", cl_name, cl_addr);
    } else {
      msg_out(norm, "%s connected", cl_addr);
      strncpy(cl_name, cl_addr, sizeof(cl_name));
    }

    i = validate_access(cl_addr, cl_name);
    if (i < 1) {
      /* access denied */
      close(cs);
      continue;
    }

    set_blocking(cs);

#ifdef USE_THREAD
    if (!threading ) {
#endif
      blocksignal(SIGHUP);
      blocksignal(SIGCHLD);
      pid = fork();
      switch (pid) {
        case -1:  /* fork child failed */
            printf("\nfork failed\n");
            break;
        case 0:   /* i am child */
            for ( i = 0; i < serv_sock_ind; i++ ) {
              close(serv_sock[i]);
            }
            setsignal(SIGCHLD, SIG_DFL);
                setsignal(SIGHUP, SIG_DFL);
                releasesignal(SIGCHLD);
                releasesignal(SIGHUP);
            ss = proto_socks(cs);
            if ( ss == -1 ) {
              close(cs);  /* may already be closed */
              exit(1);
            }
            printf("\nrelaying\n");
            relay(cs, ss);
            exit(0);
      default: /* may be parent */
            printf("\nadding proc\n");
            proclist_add(pid);
            break;
      }
      close(cs);
      releasesignal(SIGHUP);
      releasesignal(SIGCHLD);
#ifdef USE_THREAD
    } else {
      ss = proto_socks(cs);
      if ( ss == -1 ) {
        close(cs);  /* may already be closed */
        continue;
      }
      relay(cs, ss);
    }
#endif
  }
}
Ejemplo n.º 5
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 );
}
Ejemplo n.º 6
0
/*
 * Handle initial connection protocol.
 */
static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
{
  char *cp;
  int first = 1, ecode;
  struct formats *pf;
  char *filename, *mode = NULL;
  int error;
  FILE *server;
#ifdef USE_WINSOCK
  DWORD recvtimeout, recvtimeoutbak;
#endif
  char *option = (char *)"mode"; /* mode is implicit */
  int toggle = 1;

  /* Open request dump file. */
  server = fopen(REQUEST_DUMP, "ab");
  if(!server) {
    error = errno;
    logmsg("fopen() failed with error: %d %s", error, strerror(error));
    logmsg("Error opening file: %s", REQUEST_DUMP);
    return -1;
  }

  /* store input protocol */
  fprintf(server, "opcode: %x\n", tp->th_opcode);

  cp = (char *)&tp->th_stuff;
  filename = cp;
  do {
    bool endofit = true;
    while(cp < &buf.storage[size]) {
      if(*cp == '\0') {
        endofit = false;
        break;
      }
      cp++;
    }
    if(endofit)
      /* no more options */
      break;

    /* before increasing pointer, make sure it is still within the legal
       space */
    if((cp+1) < &buf.storage[size]) {
      ++cp;
      if(first) {
        /* store the mode since we need it later */
        mode = cp;
        first = 0;
      }
      if(toggle)
        /* name/value pair: */
        fprintf(server, "%s: %s\n", option, cp);
      else {
        /* store the name pointer */
        option = cp;
      }
      toggle ^= 1;
    }
    else
      /* No more options */
      break;
  } while(1);

  if(*cp) {
    nak(EBADOP);
    fclose(server);
    return 3;
  }

  /* store input protocol */
  fprintf(server, "filename: %s\n", filename);

  for(cp = mode; cp && *cp; cp++)
    if(ISUPPER(*cp))
      *cp = (char)tolower((int)*cp);

  /* store input protocol */
  fclose(server);

  for(pf = formata; pf->f_mode; pf++)
    if(strcmp(pf->f_mode, mode) == 0)
      break;
  if(!pf->f_mode) {
    nak(EBADOP);
    return 2;
  }
  ecode = validate_access(test, filename, tp->th_opcode);
  if(ecode) {
    nak(ecode);
    return 1;
  }

#ifdef USE_WINSOCK
  recvtimeout = sizeof(recvtimeoutbak);
  getsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (char*)&recvtimeoutbak, (int*)&recvtimeout);
  recvtimeout = TIMEOUT*1000;
  setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (const char*)&recvtimeout, sizeof(recvtimeout));
#endif

  if(tp->th_opcode == opcode_WRQ)
    recvtftp(test, pf);
  else
    sendtftp(test, pf);

#ifdef USE_WINSOCK
  recvtimeout = recvtimeoutbak;
  setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (const char*)&recvtimeout, sizeof(recvtimeout));
#endif

  return 0;
}
Ejemplo n.º 7
0
int serv_loop()
{

  SOCKS_STATE	state;
  SOCK_INFO	si;
  CL_INFO	client;

  int    cs;
  fd_set readable;
  int    i, n, len;
  int    error;
  pid_t  pid;

  memset(&state, 0, sizeof(state));
  memset(&si, 0, sizeof(si));
  memset(&client, 0, sizeof(client));
  state.si = &si;

#ifdef USE_THREAD
  if (threading) {
    blocksignal(SIGHUP);
    blocksignal(SIGINT);
    blocksignal(SIGUSR1);
  }
#endif

  for (;;) {
    readable = allsock;

    MUTEX_LOCK(mutex_select);
    n = select(maxsock+1, &readable, 0, 0, 0);
    if (n <= 0) {
      if (n < 0 && errno != EINTR) {
        msg_out(warn, "select: %m");
      }
      MUTEX_UNLOCK(mutex_select);
      continue;
    }

#ifdef USE_THREAD
    if ( ! threading ) {
#endif
      /* handle any queued signal flags */
      if (FD_ISSET(sig_queue[0], &readable)) {
        if (ioctl(sig_queue[0], FIONREAD, &i) != 0) {
          msg_out(crit, "ioctl: %m");
          exit(-1);
        }
        while (--i >= 0) {
          char c;
          if (read(sig_queue[0], &c, 1) != 1) {
            msg_out(crit, "read: %m");
            exit(-1);
          }
          switch(c) {
          case 'H': /* sighup */
            reload();
            break;
          case 'C': /* sigchld */
            reapchild();
            break;
          case 'T': /* sigterm */
            cleanup();
            break;
          default:
            break;
          }
        }
      }
#ifdef USE_THREAD
    }
#endif

    for ( i = 0; i < serv_sock_ind; i++ ) {
      if (FD_ISSET(serv_sock[i], &readable)) {
	n--;
	break;
      }
    }
    if ( n < 0 || i >= serv_sock_ind ) {
      MUTEX_UNLOCK(mutex_select);
      continue;
    }

    len = SS_LEN;
    cs = accept(serv_sock[i], &si.prc.addr.sa, (socklen_t *)&len);
    si.prc.len = len;
    if (cs < 0) {
      if (errno == EINTR
#ifdef SOLARIS
	  || errno == EPROTO
#endif
	  || errno == EWOULDBLOCK
	  || errno == ECONNABORTED) {
	; /* ignore */
      } else {
	/* real accept error */
	msg_out(warn, "accept: %m");
      }
      MUTEX_UNLOCK(mutex_select);
      continue;
    }
    MUTEX_UNLOCK(mutex_select);

#ifdef USE_THREAD
    if ( !threading ) {
#endif
      if (max_child > 0 && cur_child >= max_child) {
	msg_out(warn, "child: cur %d; exeedeing max(%d)",
		          cur_child, max_child);
	close(cs);
	continue;
      }
#ifdef USE_THREAD
    }
#endif

    /* get downstream-side socket name */
    len = SS_LEN;
    getsockname(cs, &si.myc.addr.sa, (socklen_t *)&len);
    si.myc.len = len;

    error = getnameinfo(&si.prc.addr.sa, si.prc.len,
			client.addr, sizeof(client.addr),
			NULL, 0,
			NI_NUMERICHOST);
    if (resolv_client) {
      error = getnameinfo(&si.prc.addr.sa, si.prc.len,
			  client.name, sizeof(client.name),
			  NULL, 0, 0);
      msg_out(norm, "%s[%s] connected", client.name, client.addr);
    } else {
      msg_out(norm, "%s connected", client.addr);
      strncpy(client.name, client.addr, sizeof(client.name));
    }

    i = validate_access(&client);
    if (i < 1) {
      /* access denied */
      close(cs);
      continue;
    }

    set_blocking(cs);
    state.s = cs;

#ifdef USE_THREAD
    if (!threading ) {
#endif
      blocksignal(SIGHUP);
      blocksignal(SIGCHLD);
      pid = fork();
      switch (pid) {
      case -1:  /* fork child failed */
	break;
      case 0:   /* i am child */
	for ( i = 0; i < serv_sock_ind; i++ ) {
	  close(serv_sock[i]);
	}
	setsignal(SIGCHLD, SIG_DFL);
        setsignal(SIGHUP, SIG_DFL);
        releasesignal(SIGCHLD);
        releasesignal(SIGHUP);
	error = proto_socks(&state);
	if ( error == -1 ) {
	  close(state.s);  /* may already be closed */
	  exit(1);
	}
	relay(&state);
	exit(0);
      default: /* may be parent */
	proclist_add(pid);
	break;
      }
      close(state.s);
      releasesignal(SIGHUP);
      releasesignal(SIGCHLD);
#ifdef USE_THREAD
    } else {
      error = proto_socks(&state);
      if ( error == -1 ) {
	close(state.s);  /* may already be closed */
	/* udp may be dynamically allocated */
	if (state.sr.udp != NULL)
	  free(state.sr.udp);
	continue;
      }
      relay(&state);
    }
#endif
  }
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
/*
 * Handle initial connection protocol.
 */
static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
{
  char *cp;
  int first = 1, ecode;
  struct formats *pf;
  char *filename, *mode = NULL;
  int error;
  FILE *server;
#ifdef USE_WINSOCK
  DWORD recvtimeout, recvtimeoutbak;
#endif

  /* Open request dump file. */
  server = fopen(REQUEST_DUMP, "ab");
  if(!server) {
    error = errno;
    logmsg("fopen() failed with error: %d %s", error, strerror(error));
    logmsg("Error opening file: %s", REQUEST_DUMP);
    return -1;
  }

  /* store input protocol */
  fprintf(server, "opcode: %x\n", tp->th_opcode);

  cp = (char *)&tp->th_stuff;
  filename = cp;
again:
  while (cp < &buf.storage[size]) {
    if (*cp == '\0')
      break;
    cp++;
  }
  if (*cp) {
    nak(EBADOP);
    fclose(server);
    return 3;
  }
  if (first) {
    mode = ++cp;
    first = 0;
    goto again;
  }
  /* store input protocol */
  fprintf(server, "filename: %s\n", filename);

  for (cp = mode; cp && *cp; cp++)
    if(ISUPPER(*cp))
      *cp = (char)tolower((int)*cp);

  /* store input protocol */
  fprintf(server, "mode: %s\n", mode);
  fclose(server);

  for (pf = formata; pf->f_mode; pf++)
    if (strcmp(pf->f_mode, mode) == 0)
      break;
  if (!pf->f_mode) {
    nak(EBADOP);
    return 2;
  }
  ecode = validate_access(test, filename, tp->th_opcode);
  if (ecode) {
    nak(ecode);
    return 1;
  }

#ifdef USE_WINSOCK
  recvtimeout = sizeof(recvtimeoutbak);
  getsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (char*)&recvtimeoutbak, (int*)&recvtimeout);
  recvtimeout = TIMEOUT*1000;
  setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (const char*)&recvtimeout, sizeof(recvtimeout));
#endif

  if (tp->th_opcode == opcode_WRQ)
    recvtftp(test, pf);
  else
    sendtftp(test, pf);

#ifdef USE_WINSOCK
  recvtimeout = recvtimeoutbak;
  setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (const char*)&recvtimeout, sizeof(recvtimeout));
#endif

  return 0;
}