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; }
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; }
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; }
/* *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