static void test_network(void) { resolve_server(); if (_state.s_nt_ip.s_addr == INADDR_ANY) { xprintf(XP_ALWAYS, "Won't test network - can't resolve %s\n", _conf.cf_test_server); return; } xprintf(XP_ALWAYS, "Testing network via %s\n", inet_ntoa(_state.s_nt_ip)); test_port(80); test_port(7777); }
krb5_error_code k5_sendto(krb5_context context, const krb5_data *message, const krb5_data *realm, const struct serverlist *servers, k5_transport_strategy strategy, struct sendto_callback_info* callback_info, krb5_data *reply, struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *server_used, /* return 0 -> keep going, 1 -> quit */ int (*msg_handler)(krb5_context, const krb5_data *, void *), void *msg_handler_data) { int pass; time_ms delay; krb5_error_code retval; struct conn_state *conns = NULL, *state, **tailptr, *next, *winner; size_t s; struct select_state *sel_state = NULL, *seltemp; char *udpbuf = NULL; krb5_boolean done = FALSE; *reply = empty_data(); /* One for use here, listing all our fds in use, and one for * temporary use in service_fds, for the fds of interest. */ sel_state = malloc(2 * sizeof(*sel_state)); if (sel_state == NULL) { retval = ENOMEM; goto cleanup; } seltemp = &sel_state[1]; cm_init_selstate(sel_state); /* First pass: resolve server hosts, communicate with resulting addresses * of the preferred transport, and wait 1s for an answer from each. */ for (s = 0; s < servers->nservers && !done; s++) { /* Find the current tail pointer. */ for (tailptr = &conns; *tailptr != NULL; tailptr = &(*tailptr)->next); retval = resolve_server(context, realm, servers, s, strategy, message, &udpbuf, &conns); if (retval) goto cleanup; for (state = *tailptr; state != NULL && !done; state = state->next) { /* Contact each new connection, deferring those which use the * non-preferred RFC 4120 transport. */ if (state->defer) continue; if (maybe_send(context, state, message, sel_state, realm, callback_info)) continue; done = service_fds(context, sel_state, 1000, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); } } /* Complete the first pass by contacting servers of the non-preferred RFC * 4120 transport (if given), waiting 1s for an answer from each. */ for (state = conns; state != NULL && !done; state = state->next) { if (!state->defer) continue; if (maybe_send(context, state, message, sel_state, realm, callback_info)) continue; done = service_fds(context, sel_state, 1000, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); } /* Wait for two seconds at the end of the first pass. */ if (!done) { done = service_fds(context, sel_state, 2000, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); } /* Make remaining passes over all of the connections. */ delay = 4000; for (pass = 1; pass < MAX_PASS && !done; pass++) { for (state = conns; state != NULL && !done; state = state->next) { if (maybe_send(context, state, message, sel_state, realm, callback_info)) continue; done = service_fds(context, sel_state, 1000, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); if (sel_state->nfds == 0) break; } /* Wait for the delay backoff at the end of this pass. */ if (!done) { done = service_fds(context, sel_state, delay, conns, seltemp, realm, msg_handler, msg_handler_data, &winner); } if (sel_state->nfds == 0) break; delay *= 2; } if (sel_state->nfds == 0 || !done || winner == NULL) { retval = KRB5_KDC_UNREACH; goto cleanup; } /* Success! */ *reply = make_data(winner->in.buf, winner->in.pos); retval = 0; winner->in.buf = NULL; if (server_used != NULL) *server_used = winner->server_index; if (remoteaddr != NULL && remoteaddrlen != 0 && *remoteaddrlen > 0) (void)getpeername(winner->fd, remoteaddr, remoteaddrlen); TRACE_SENDTO_KDC_RESPONSE(context, reply->length, &winner->addr); cleanup: for (state = conns; state != NULL; state = next) { next = state->next; if (state->fd != INVALID_SOCKET) { if (socktype_for_transport(state->addr.transport) == SOCK_STREAM) TRACE_SENDTO_KDC_TCP_DISCONNECT(context, &state->addr); closesocket(state->fd); free_http_tls_data(context, state); } if (state->state == READING && state->in.buf != udpbuf) free(state->in.buf); if (callback_info) { callback_info->pfn_cleanup(callback_info->data, &state->callback_buffer); } free(state); } if (reply->data != udpbuf) free(udpbuf); free(sel_state); return retval; }
/* Forwards a message to its' destination. @param File descriptor of the message. <---- change to char * and get FD off that @param Destination server as a c string. @return */ int forwardMessage(char * file_to_foward, char * dest_server_string) { print_to_log("Forward message routine starting.", LOG_INFO); //Find MX record struct sockaddr_storage dest_sockaddr; int32_t file_to_foward_descriptor; uint32_t mx_family = -1; mx_family = resolve_server(dest_server_string, &dest_sockaddr); uint32_t temp_socket = 0; if ((mx_family!=AF_INET)&&(mx_family!=AF_INET6)) { #ifdef DEBUG printf("Invalid mx_family. Cannot forward mail. mx_family = %d\n", mx_family); #endif /*DEBUG*/ print_to_log("Invalid MX family on message forward. Cannot forward message.", LOG_INFO); return -1; } //IPv4 case if(mx_family==AF_INET) { temp_socket = socket(AF_INET, SOCK_STREAM, 0); if ((connect(temp_socket, (struct sockaddr_in *)&dest_sockaddr, sizeof(struct sockaddr_in)))<0) { print_to_log("Connecting on send port has failed. Cannot forward message.", LOG_ERR); perror("connect"); return -1; } //Write file to connected socket char temp_byte; if ((file_to_foward_descriptor = open(file_to_foward, O_RDONLY))<0) { print_to_log("Cannot open file for forwarding.", LOG_ERR); return -1; } while ((temp_byte=read(file_to_foward_descriptor, &temp_byte, 1))!=-1) { write(temp_socket, &temp_byte, 1); } #ifdef DEBUG printf("Message forwarded via IPv4\n"); #endif /*DEBUG*/ print_to_log("Forward message via IPv4 complete", LOG_INFO); } if(mx_family==AF_INET6) { temp_socket = socket(AF_INET6, SOCK_STREAM, 0); if ((connect(temp_socket, (struct sockaddr_in6 *)&dest_sockaddr, sizeof(struct sockaddr_in6)))<0) { print_to_log("Connecting on send port has failed. Cannot forward message.", LOG_ERR); perror("connect"); return -1; } //Write file to connected socket char temp_byte; while ((temp_byte=read(file_to_foward_descriptor, &temp_byte, 1))!=-1) { write(temp_socket, &temp_byte, 1); } print_to_log("Forward message via IPv6 complete", LOG_INFO); } close(temp_socket); return 0; }
int main(int argc, char *argv[]) { int ch; #ifdef __WIN32__ WSADATA wsadata; if (WSAStartup(MAKEWORD(1,1), &wsadata) == SOCKET_ERROR) errx(1, "WSAStartup()"); #endif _conf.cf_port = 666; _conf.cf_ctl = TCPCRYPT_CTLPATH; _conf.cf_test = -1; _conf.cf_test_server = "check.tcpcrypt.org"; while ((ch = getopt(argc, argv, "hp:vdu:camnPt:T:S:Dx:NC:M:Rifs:V")) != -1) { switch (ch) { case 'i': _conf.cf_disable_timers = 1; break; case 'R': _conf.cf_rsa_client_hack = 1; break; case 'M': _conf.cf_mac = atoi(optarg); break; case 'C': _conf.cf_cipher = atoi(optarg); break; case 'N': _conf.cf_nat = 1; break; case 'D': _conf.cf_debug = 1; break; case 'S': profile_setopt(PROFILE_TIME_SOURCE, atoi(optarg)); break; case 'x': add_param(&_conf.cf_divert_params, optarg); break; case 'T': add_param(&_conf.cf_test_params, optarg); break; case 't': _conf.cf_test = atoi(optarg); break; case 'P': _conf.cf_profile++; break; case 'n': _conf.cf_dummy = 1; break; case 'a': _conf.cf_accept = 1; break; case 'm': _conf.cf_modify = 1; break; case 'c': _conf.cf_nocache = 1; break; case 'u': _conf.cf_ctl = atoi(optarg); break; case 'd': _conf.cf_disable = 1; break; case 'p': _conf.cf_port = atoi(optarg); break; case 'v': _conf.cf_verbose++; break; case 'V': printf("tcpcrypt version %s\n", TCPCRYPT_VERSION); exit(0); case 'f': _conf.cf_disable_network_test = 1; break; case 's': _conf.cf_test_server = optarg; break; case 'h': default: usage(argv[0]); exit(0); break; } } resolve_server(); if (signal(SIGINT, sig) == SIG_ERR) err(1, "signal()"); if (signal(SIGTERM, sig) == SIG_ERR) err(1, "signal()"); #ifndef __WIN32__ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) err(1, "signal()"); #endif profile_setopt(PROFILE_DISCARD, 3); profile_setopt(PROFILE_ENABLE, _conf.cf_profile); pwn(); cleanup(); exit(0); }
krb5_error_code k5_sendto(krb5_context context, const krb5_data *message, const struct serverlist *servers, int socktype1, int socktype2, struct sendto_callback_info* callback_info, krb5_data *reply, struct sockaddr *remoteaddr, socklen_t *remoteaddrlen, int *server_used, /* return 0 -> keep going, 1 -> quit */ int (*msg_handler)(krb5_context, const krb5_data *, void *), void *msg_handler_data) { int pass, delay; krb5_error_code retval; struct conn_state *conns = NULL, *state, **tailptr, *next, *winner; size_t s; struct select_state *sel_state = NULL, *seltemp; char *udpbuf = NULL; krb5_boolean done = FALSE; reply->data = 0; reply->length = 0; /* One for use here, listing all our fds in use, and one for * temporary use in service_fds, for the fds of interest. */ sel_state = malloc(2 * sizeof(*sel_state)); if (sel_state == NULL) { retval = ENOMEM; goto cleanup; } seltemp = &sel_state[1]; sel_state->max = 0; sel_state->nfds = 0; sel_state->end_time.tv_sec = sel_state->end_time.tv_usec = 0; FD_ZERO(&sel_state->rfds); FD_ZERO(&sel_state->wfds); FD_ZERO(&sel_state->xfds); /* First pass: resolve server hosts, communicate with resulting addresses * of the preferred socktype, and wait 1s for an answer from each. */ for (s = 0; s < servers->nservers && !done; s++) { /* Find the current tail pointer. */ for (tailptr = &conns; *tailptr != NULL; tailptr = &(*tailptr)->next); retval = resolve_server(context, servers, s, socktype1, socktype2, message, &udpbuf, &conns); if (retval) goto cleanup; for (state = *tailptr; state != NULL && !done; state = state->next) { /* Contact each new connection whose socktype matches socktype1. */ if (state->socktype != socktype1) continue; if (maybe_send(context, state, sel_state, callback_info)) continue; done = service_fds(context, sel_state, 1, conns, seltemp, msg_handler, msg_handler_data, &winner); } } /* Complete the first pass by contacting servers of the non-preferred * socktype (if given), waiting 1s for an answer from each. */ for (state = conns; state != NULL && !done; state = state->next) { if (state->socktype != socktype2) continue; if (maybe_send(context, state, sel_state, callback_info)) continue; done = service_fds(context, sel_state, 1, state, seltemp, msg_handler, msg_handler_data, &winner); } /* Wait for two seconds at the end of the first pass. */ if (!done) { done = service_fds(context, sel_state, 2, conns, seltemp, msg_handler, msg_handler_data, &winner); } /* Make remaining passes over all of the connections. */ delay = 4; for (pass = 1; pass < MAX_PASS && !done; pass++) { for (state = conns; state != NULL && !done; state = state->next) { if (maybe_send(context, state, sel_state, callback_info)) continue; done = service_fds(context, sel_state, 1, conns, seltemp, msg_handler, msg_handler_data, &winner); if (sel_state->nfds == 0) break; } /* Wait for the delay backoff at the end of this pass. */ if (!done) { done = service_fds(context, sel_state, delay, conns, seltemp, msg_handler, msg_handler_data, &winner); } if (sel_state->nfds == 0) break; delay *= 2; } if (sel_state->nfds == 0 || !done || winner == NULL) { retval = KRB5_KDC_UNREACH; goto cleanup; } /* Success! */ TRACE_SENDTO_KDC_RESPONSE(context, winner); reply->data = winner->x.in.buf; reply->length = winner->x.in.pos - winner->x.in.buf; retval = 0; winner->x.in.buf = NULL; if (server_used != NULL) *server_used = winner->server_index; if (remoteaddr != NULL && remoteaddrlen != 0 && *remoteaddrlen > 0) (void)getpeername(winner->fd, remoteaddr, remoteaddrlen); cleanup: for (state = conns; state != NULL; state = next) { next = state->next; if (state->fd != INVALID_SOCKET) closesocket(state->fd); if (state->state == READING && state->x.in.buf != udpbuf) free(state->x.in.buf); if (callback_info) { callback_info->pfn_cleanup(callback_info->context, &state->callback_buffer); } free(state); } if (reply->data != udpbuf) free(udpbuf); free(sel_state); return retval; }