static void emc_server_accept_cb (struct ev_loop *loop, ev_io *w, int revents) { struct emc_tls_server_context *ctx; struct sockaddr_storage sockaddr; struct sockaddr_in *sockaddr4 = (struct sockaddr_in *) &sockaddr; struct sockaddr_in6 *sockaddr6 = (struct sockaddr_in6 *) &sockaddr; struct in6_addr addr; unsigned int len_inet = sizeof sockaddr; nussl_session *nussl_sess; int socket; int sport; char address[INET6_ADDRSTRLEN]; struct emc_client_context *client_ctx = NULL; ctx = w->data; nussl_sess = nussl_session_accept(ctx->nussl); if (nussl_sess == NULL) { log_printf(DEBUG_LEVEL_WARNING, "Error while accepting new connection: %s", nussl_get_error(ctx->nussl)); return; } if (nussl_session_getpeer(nussl_sess, (struct sockaddr *) &sockaddr, &len_inet) != NUSSL_OK) { log_printf(DEBUG_LEVEL_WARNING, "WARNING New client connection failed during nussl_session_getpeer(): %s", nussl_get_error(ctx->nussl)); free(nussl_sess); return; } socket = nussl_session_get_fd(nussl_sess); /* Extract client address (convert it to IPv6 if it's IPv4) */ if (sockaddr6->sin6_family == AF_INET) { ipv4_to_ipv6(sockaddr4->sin_addr, &addr); sport = ntohs(sockaddr4->sin_port); } else { addr = sockaddr6->sin6_addr; sport = ntohs(sockaddr6->sin6_port); } format_ipv6(&addr, address, sizeof(address), NULL); log_printf(DEBUG_LEVEL_DEBUG, "DEBUG emc: user connection attempt from %s", address); client_ctx = malloc(sizeof(struct emc_client_context)); client_ctx->nussl = nussl_sess; strncpy(client_ctx->address, address, sizeof(client_ctx->address)); client_ctx->tls_server_ctx = ctx; client_ctx->state = EMC_CLIENT_STATE_HANDSHAKE; g_thread_pool_push(server_ctx->pool_tls_handshake, client_ctx, NULL); }
struct in6_addr*ipv6_inet_pton(char*ipstring){ if(ipstring==NULL)return NULL; struct in6_addr*ip=malloc(sizeof(struct in6_addr));//IP-Adresse if(!inet_pton(AF_INET6,ipstring,ip)){ //Es handelt sich nicht um eine IPv6 Adresse! struct in_addr ipv4;//Fuer Konvertierung notwendig if(!inet_pton(AF_INET,ipstring,&ipv4)){ //Es handelt sich nicht um eine IPv4 Adresse! //Adresse kann nicht konvertiert werden! free(ip); //parseerrorcounter++;//Fehlerzaehler korrigiert return NULL; } //Wird konvertiert ipv4_to_ipv6(&ipv4,ip); } return ip; }
/** * Function called on new client connection: * - Call accept() * - Drop client if there are to much clients or if NuAuth is in reload * - Create a client_connection structure * - Add client to ::pre_client_list * - Add client to ::tls_sasl_worker queue (see sasl_worker()) * * \return If an error occurs returns 1, else returns 0. */ int tls_user_accept(struct tls_user_context_t *context) { struct sockaddr_storage sockaddr; struct sockaddr_in *sockaddr4 = (struct sockaddr_in *) &sockaddr; struct sockaddr_in6 *sockaddr6 = (struct sockaddr_in6 *) &sockaddr; struct in6_addr addr; unsigned int len_inet = sizeof sockaddr; struct client_connection *current_client_conn; struct pre_client_elt *new_pre_client; int socket; gint option_value; unsigned short sport; char address[INET6_ADDRSTRLEN]; current_client_conn = g_new0(struct client_connection, 1); current_client_conn->nussl = nussl_session_accept(context->nussl); if ( ! current_client_conn->nussl ) { /* can be triggered by EAGAIN on non blocking accept socket */ g_free(current_client_conn); return 1; } if (nussl_session_getpeer(current_client_conn->nussl, (struct sockaddr *) &sockaddr, &len_inet) != NUSSL_OK) { log_message(WARNING, DEBUG_AREA_MAIN | DEBUG_AREA_USER, "New client connection failed during nussl_session_getpeer(): %s", nussl_get_error(context->nussl)); g_free(current_client_conn); return 1; } socket = nussl_session_get_fd(current_client_conn->nussl); /* if system is in reload: drop new client */ if (nuauthdatas->need_reload) { shutdown(socket, SHUT_RDWR); close(socket); return 0; } /* Extract client address (convert it to IPv6 if it's IPv4) */ /* if (sockaddr.ss_family == AF_INET) { -> same as tls_nufw.c */ if (sockaddr6->sin6_family == AF_INET) { ipv4_to_ipv6(sockaddr4->sin_addr, &addr); sport = ntohs(sockaddr4->sin_port); } else { addr = sockaddr6->sin6_addr; sport = ntohs(sockaddr6->sin6_port); } format_ipv6(&addr, address, sizeof(address), NULL); log_message(DEBUG, DEBUG_AREA_MAIN | DEBUG_AREA_USER, "nuauth: user connection attempt from %s\n", address); if (get_number_of_clients() >= context->nuauth_tls_max_clients) { log_message(WARNING, DEBUG_AREA_MAIN | DEBUG_AREA_USER, "too many clients (%d configured)", context->nuauth_tls_max_clients); shutdown(socket, SHUT_RDWR); close(socket); return 1; } current_client_conn->socket = socket; current_client_conn->addr = addr; current_client_conn->sport = sport; current_client_conn->str_addr = g_strdup(address); current_client_conn->srv_context = context; /* Set KEEP ALIVE on connection */ option_value = 1; setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &option_value, sizeof(option_value)); /* give the connection to a separate thread */ /* add element to pre_client create pre_client_elt */ new_pre_client = g_new0(struct pre_client_elt, 1); new_pre_client->socket = socket; new_pre_client->validity = time(NULL) + context->nuauth_auth_nego_timeout; g_static_mutex_lock(&pre_client_list_mutex); pre_client_list = g_slist_prepend(pre_client_list, new_pre_client); g_static_mutex_unlock(&pre_client_list_mutex); thread_pool_push(nuauthdatas->tls_sasl_worker, current_client_conn, NULL); return 0; }