Example #1
0
void
process_udp_request(int ksoc, struct packet *pkt)
{
    char *packet = pkt->data;
    unsigned char version, auth_msg_type;

    version = *packet++;
    if (version != KRB_PROT_VERSION) {
	err_packet(ksoc, pkt, KERB_ERR_PKT_VER,
		   "packet version number unknown");
	return;
    }
    auth_msg_type = *packet++;
    pkt->byteOrder = auth_msg_type & 1;
    pkt->rest = packet;
    switch (auth_msg_type & ~1) {
    case AUTH_MSG_KDC_REQUEST:
	process_udp_auth(ksoc, pkt);
	break;
    case AUTH_MSG_APPL_REQUEST:
	process_udp_appl(ksoc, pkt);
	break;
    default:
	printf("unknown msg type 0x%x\n", auth_msg_type);
	err_packet(ksoc, pkt, KERB_ERR_BAD_MSG_TYPE,
		   "message type not supported");
	return;
    }
    return;
}
Example #2
0
int
process_udp_appl(int ksoc, struct packet *pkt)
{
    char *packet = pkt->rest;
    afs_int32 kvno;
    char realm[MAXKTCREALMLEN];
    char ticket[MAXKTCTICKETLEN];
    char auth[3 * MAXKTCNAMELEN + 4 + 5];
    int slen;
    int ticketLen, authLen;
    afs_int32 code;

    if (krb_udp_debug) {
	printf("Processing APPL Request\n");
    }
    kvno = *packet++;
    getstr(realm);
    ticketLen = *(unsigned char *)packet++;
    authLen = *(unsigned char *)packet++;
    if (ticketLen > sizeof(ticket)) {
	err_packet(ksoc, pkt, KERB_ERR_TEXT_LENGTH, "ticket too long");
	return -1;
    }
    memcpy(ticket, packet, ticketLen);
    packet += ticketLen;
    if (authLen > sizeof(auth)) {
	err_packet(ksoc, pkt, KERB_ERR_TEXT_LENGTH, "authenticator too long");
	return -1;
    }
    memcpy(auth, packet, authLen);
    pkt->rest = packet + authLen;
    code =
	UDP_GetTicket(ksoc, pkt, kvno, realm, ticket, ticketLen, auth,
		      authLen);
    if (code) {
	if (code == KANOENT)
	    code = KERB_ERR_PRINCIPAL_UNKNOWN;
	err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
	return -1;
    }
    return 0;
}
Example #3
0
int
process_udp_auth(int ksoc, struct packet *pkt)
{
    char *packet = pkt->rest;
    char name[MAXKTCNAMELEN];
    char inst[MAXKTCNAMELEN];
    char realm[MAXKTCREALMLEN];
    char sname[MAXKTCNAMELEN];
    char sinst[MAXKTCNAMELEN];
    int slen;
    Date now = time(0);
    Date startTime, endTime;
    unsigned char lifetime;
    afs_int32 code;

    pkt->name = packet;
    getstr(name);
    pkt->inst = packet;
    getstr(inst);
    pkt->realm = packet;
    getstr(realm);
    if (krb_udp_debug) {
	printf("Processing KDC Request from '%s'.'%s'@'%s'\n", name, inst,
	       realm);
    }

    if ((strlen(realm) > 0) && (strcmp(realm, lrealm) != 0)) {
	err_packet(ksoc, pkt, KERB_ERR_NONNULL_REALM,
		   "null realm name not allowed");
	return -1;
    }
    memcpy(&startTime, packet, sizeof(startTime));
    packet += sizeof(startTime);
    startTime = ktohl(pkt->byteOrder, startTime);
    pkt->time = startTime;
    lifetime = *packet++;
    endTime = life_to_time(startTime, lifetime);
    code = tkt_CheckTimes(startTime, endTime, now);
    if (code < 0) {
	err_packet(ksoc, pkt, KERB_ERR_BAD_LIFETIME,
		   "requested ticket lifetime invalid");
	return -1;
    }
    getstr(sname);
    getstr(sinst);
    if ((packet - pkt->data) != pkt->len) {
	err_packet(ksoc, pkt, KERB_ERR_PKT_LENGTH,
		   "packet length inconsistent");
	return -1;
    }
    pkt->rest = packet;
    code =
	UDP_Authenticate(ksoc, &pkt->from, name, inst, startTime, endTime,
			 sname, sinst);
    if (code) {
	if (code == KANOENT) {
	    code = KERB_ERR_PRINCIPAL_UNKNOWN;
	    err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
	} else if (code == KAPWEXPIRED) {
	    code = KERB_ERR_NAME_EXP;
	    err_packet(ksoc, pkt, code, "password has expired");
	} else
	    err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
    }
    return 0;
}
Example #4
0
/*
*This function is called when the client would like to upload a file to the server.
*/
void
tsend (char *pFilename, struct sockaddr_in server, char *pMode, int sock)
{
  int len, server_len, opcode, ssize = 0, n, i, j, bcount = 0, tid;
  unsigned short int count = 0, rcount = 0, acked = 0;
  unsigned char filebuf[MAXDATASIZE + 1];
  unsigned char packetbuf[MAXACKFREQ][MAXDATASIZE + 12],
    recvbuf[MAXDATASIZE + 12];
  char filename[128], mode[12], *bufindex;	//fullpath[196],
  struct sockaddr_in ack;

  FILE *fp;			/* pointer to the file we will be sending */

  strcpy (filename, pFilename);	//copy the pointer to the filename into a real array
  strcpy (mode, pMode);		//same as above

  if (debug)
    printf ("Client: branched to file send function\n");

/*At this point I have to wait to recieve an ACK from the server before I start sending the file*/
  /*open the file to read */
  fp = fopen (filename, "r");
  if (fp == NULL)
    {				//if the pointer is null then the file can't be opened - Bad perms OR no such file
      if (debug)
	printf ("Client: sending bad file: file not found (%s)\n", filename);
      return;
    }
  else
    {
      if (debug)
	printf ("Client: Sending file... (source: %s)\n", filename);

    }
//get ACK for WRQ
/* The following 'for' loop is used to recieve/timeout ACKs */
  for (j = 0; j < RETRIES - 2; j++)
    {
      server_len = sizeof (ack);
      errno = EAGAIN;
      n = -1;
      for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)
	{
	  n = recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,
			(struct sockaddr *) &ack, (socklen_t *) & server_len);
	  usleep (1000);
	}


      /* if(debug)
         ip_port (ack);    print the vlaue recived from the server */


      tid = ntohs (ack.sin_port);	//get the tid of the server.
      server.sin_port = htons (tid);	//set the tid for rest of the transfer


      if (n < 0 && errno != EAGAIN)
	{
	  if (debug)
	    printf
	      ("Client: could not receive from the server (errno: %d n: %d)\n",
	       errno, n);
	  //resend packet
	}
      else if (n < 0 && errno == EAGAIN)
	{
	  if (debug)
	    printf ("Client: Timeout waiting for ack (errno: %d n: %d)\n",
		    errno, n);
	  //resend packet
	}
      else
	{			/*changed client to server here */
	  if (server.sin_addr.s_addr != ack.sin_addr.s_addr)	/* checks to ensure send to ip is same from ACK IP */
	    {
	      if (debug)
		printf
		  ("Client: Error recieving ACK (ACK from invalid address)\n");
	      j--;		/* in this case someone else connected to our port. Ignore this fact and retry getting the ack */
	      continue;
	    }
	  if (tid != ntohs (server.sin_port))	/* checks to ensure get from the correct TID */
	    {
	      if (debug)
		printf
		  ("Client: Error recieving file (data from invalid tid)\n");
	      len = err_packet (5, err_msg[5], buf);
	      if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len)	/* send the data packet */
		{
		  printf
		    ("Client: Mismatch in number of sent bytes while trying to send mode error packet\n");
		}
	      /* if (debug)
	         ip_port(server); */
	      j--;
	      continue;		/* we aren't going to let another connection spoil our first connection */
	    }

/* this formatting code is just like the code in the main function */
	  bufindex = (char *) recvbuf;	//start our pointer going
	  if (bufindex++[0] != 0x00)
	    printf ("Client: bad first nullbyte!\n");
	  opcode = *bufindex++;

	  rcount = *bufindex++ << 8;
	  rcount &= 0xff00;
	  rcount += (*bufindex++ & 0x00ff);
	  if (opcode != 4 || rcount != count)	/* ack packet should have code 4 (ack) and should be acking the packet we just sent */
	    {
	      if (debug)
		printf
		  ("Client: Remote host failed to ACK proper data packet # %d (got OP: %d Block: %d)\n",
		   count, opcode, rcount);
/* sending error message */
	      if (opcode > 5)
		{

		  len = err_packet (4, err_msg[4], buf);
		  if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len)	/* send the data packet */
		    {
		      printf
			("Client: Mismatch in number of sent bytes while trying to send mode error packet\n");
		    }
		}
	      /* from here we will loop back and resend */
	      /* if (debug)
	         ip_port(server); */
	    }
	  else
	    {
	      if (debug)
		printf ("Client: Remote host successfully ACK'd (#%d)\n",
			rcount);
	      break;
	    }
	}			//end of else
      if (debug)
	printf ("Client: Ack(s) lost. Resending complete.\n");

    }
/* The ack sending 'for' loop ends here */



  memset (filebuf, 0, sizeof (filebuf));	//clear the filebuf
  while (1)			/* our break statement will escape us when we are done */
    {
      acked = 0;
      ssize = fread (filebuf, 1, datasize, fp);
      if (debug)
	{
	  printf
	    ("The first data block has been read from the file and will be sent to the server\n");
	  printf ("The size read from the file is: %d\n", ssize);
	}

      count++;			/* count number of datasize byte portions we read from the file */
      if (count == 1)		/* we always look for an ack on the FIRST packet */
	bcount = 0;
      else if (count == 2)	/* The second packet will always start our counter at zreo. This special case needs to exist to avoid a DBZ when count = 2 - 2 = 0 */
	bcount = 0;
      else
	bcount = (count - 2) % ackfreq;

      sprintf ((char *) packetbuf[bcount], "%c%c%c%c", 0x00, 0x03, 0x00, 0x00);	/* build data packet but write out the count as zero */
      memcpy ((char *) packetbuf[bcount] + 4, filebuf, ssize);
      len = 4 + ssize;
      packetbuf[bcount][2] = (count & 0xFF00) >> 8;	//fill in the count (top number first)
      packetbuf[bcount][3] = (count & 0x00FF);	//fill in the lower part of the count
      if (debug)
	printf ("Client: Sending packet # %04d (length: %d file chunk: %d)\n",
		count, len, ssize);
      /* send the data packet */
      if (sendto
	  (sock, packetbuf[bcount], len, 0, (struct sockaddr *) &server,
	   sizeof (server)) != len)
	{
	  if (debug)
	    printf ("Client: Mismatch in number of sent bytes\n");
	  return;
	}
      if (debug)
	{
	  ip_port (server);
	  printf ("==count: %d  bcount: %d  ssize: %d  datasize: %d\n", count,
		  bcount, ssize, datasize);
	}
      //if ((count - 1) == 0 || ((count - 1) % ackfreq) == 0 || ssize != datasize)
      if (((count) % ackfreq) == 0 || ssize != datasize)
	{
	  if (debug)
	    printf ("-- I will get an ACK\n");
/* The following 'for' loop is used to recieve/timeout ACKs */
	  for (j = 0; j < RETRIES; j++)
	    {
	      server_len = sizeof (ack);
	      errno = EAGAIN;
	      n = -1;
	      for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)
		{
		  n =
		    recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,
			      (struct sockaddr *) &ack,
			      (socklen_t *) & server_len);
		  /* if (debug)
		     ip_port(ack); */
		  usleep (1000);
		}
	      if (n < 0 && errno != EAGAIN)
		{
		  if (debug)
		    printf
		      ("Client: could not receive from the server (errno: %d n: %d)\n",
		       errno, n);
		  //resend packet
		}
	      else if (n < 0 && errno == EAGAIN)
		{
		  if (debug)
		    printf
		      ("Client: Timeout waiting for ack (errno: %d n: %d)\n",
		       errno, n);
		  //resend packet
		}
	      else
		{		/* checks to ensure send to ip is same from ACK IP */
		  if (server.sin_addr.s_addr != ack.sin_addr.s_addr)
		    {
		      if (debug)
			printf
			  ("Client: Error recieving ACK (ACK from invalid address)\n");
		      /* in this case someone else connected to our port. Ignore this fact and retry getting the ack */
		      j--;
		      continue;
		    }
		  if (tid != ntohs (server.sin_port))	/* checks to ensure get from the correct TID */
		    {
		      if (debug)
			printf
			  ("Client: Error recieving file (data from invalid tid)\n");
		      len = err_packet (5, err_msg[5], buf);
		      /* send the data packet */
		      if (sendto
			  (sock, buf, len, 0, (struct sockaddr *) &server,
			   sizeof (server)) != len)
			{
			  printf
			    ("Client: Mismatch in number of sent bytes while trying to send mode error packet\n");
			}
		      /*if (debug)
		         ip_port(server);  */
		      j--;

		      continue;	/* we aren't going to let another connection spoil our first connection */
		    }

/* this formatting code is just like the code in the main function */
		  bufindex = (char *) recvbuf;	//start our pointer going
		  if (bufindex++[0] != 0x00)
		    printf ("Client: bad first nullbyte!\n");
		  opcode = *bufindex++;

		  rcount = *bufindex++ << 8;
		  rcount &= 0xff00;
		  rcount += (*bufindex++ & 0x00ff);
		  if (opcode != 4 || rcount != count)	/* ack packet should have code 4 (ack) and should be acking the packet we just sent */
		    {
		      if (debug)
			printf
			  ("Client: Remote host failed to ACK proper data packet # %d (got OP: %d Block: %d)\n",
			   count, opcode, rcount);
		      /* sending error message */
		      if (opcode > 5)
			{
			  len = err_packet (4, err_msg[4], buf);
			  if (sendto (sock, buf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len)	/* send the data packet */
			    {
			      printf
				("Client: Mismatch in number of sent bytes while trying to send mode error packet\n");
			    }
			  /*if (debug)
			     ip_port(server); */
			}
		      /* from here we will loop back and resend */
		    }
		  else
		    {
		      if (debug)
			printf
			  ("Client: Remote host successfully ACK'd (#%d)\n",
			   rcount);
		      break;
		    }
		}
	      for (i = 0; i <= bcount; i++)
		{
		  if (sendto (sock, packetbuf[i], len, 0, (struct sockaddr *) &server, sizeof (server)) != len)	/* resend the data packet */
		    {
		      if (debug)
			printf ("Client: Mismatch in number of sent bytes\n");
		      return;
		    }
		  if (debug)
		    {
		      printf ("Client: Ack(s) lost. Resending: %d\n",
			      count - bcount + i);
		      ip_port (server);
		    }
		}
	      if (debug)
		printf ("Client: Ack(s) lost. Resending complete.\n");

	    }
/* The ack sending 'for' loop ends here */

	}
      else if (debug)
	{
	  printf
	    ("Client: Not attempting to recieve ack. Not required. count: %d\n",
	     count);
	  n = recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT, (struct sockaddr *) &ack, (socklen_t *) & server_len);	/* just do a quick check incase the remote host is trying with ackfreq = 1 */
	  /*if (debug)
	     ip_port(ack); */
	}

      if (j == RETRIES)
	{
	  if (debug)
	    printf ("Client: Ack Timeout. Aborting transfer\n");
	  fclose (fp);

	  return;
	}
      if (ssize != datasize)
	break;

      memset (filebuf, 0, sizeof (filebuf));	/* fill the filebuf with zeros so that when the fread fills it, it is a null terminated string */
    }

  fclose (fp);
  if (debug)
    printf ("Client: File sent successfully\n");

  return;
}				//end of tsend function