void add_client(int socket, gpointer datas) { user_session_t *c_session = (user_session_t *) datas; ip_sessions_t *ipsessions; gpointer key; lock_client_datas(); g_hash_table_insert(client_conn_hash, GINT_TO_POINTER(socket), datas); /* need to create entry in ip hash ? */ ipsessions = g_hash_table_lookup(client_ip_hash, &c_session->addr); if (ipsessions == NULL) { ipsessions = g_new0(ip_sessions_t, 1); ipsessions->proto_version = c_session->proto_version; ipsessions->sessions = NULL; key = g_memdup(&c_session->addr, sizeof(c_session->addr)); g_hash_table_replace(client_ip_hash, key, ipsessions); } /* let's assume backward compatibility, older client wins */ /* TODO: Add a configuration variable for this choice */ if (c_session->proto_version < ipsessions->proto_version) { char buffer[256]; format_ipv6(&c_session->addr, buffer, 256, NULL); ipsessions->proto_version = c_session->proto_version; log_message(WARNING, DEBUG_AREA_USER, "User %s on %s uses older version of client", c_session->user_name, buffer); } if (c_session->proto_version > ipsessions->proto_version) { char buffer[256]; format_ipv6(&c_session->addr, buffer, 256, NULL); log_message(WARNING, DEBUG_AREA_USER, "User %s on %s uses newer version of client", c_session->user_name, buffer); } ipsessions->sessions = g_slist_prepend(ipsessions->sessions, c_session); unlock_client_datas(); }
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); }
G_MODULE_EXPORT void auth_error_log(user_session_t * session, nuauth_auth_error_t error, const char *text, gpointer params_ptr) { char ipaddr[INET6_ADDRSTRLEN]; format_ipv6(&session->addr, ipaddr, INET6_ADDRSTRLEN, NULL); g_message("Authentication error: %s", text); g_message("Authentication error: user: %s from %s (port %d), protocol version %d", session->user_name, ipaddr, session->sport, session->proto_version); }
G_MODULE_EXPORT int user_session_logs(user_session_t * c_session, session_state_t state, gpointer params) { char *prefix = "[nuauth] "; char address[INET6_ADDRSTRLEN]; format_ipv6(&c_session->addr, address, INET6_ADDRSTRLEN, NULL); switch (state) { case SESSION_OPEN: g_message("%sUser %s connect on %s", prefix, c_session->user_name, address); break; case SESSION_CLOSE: g_message("%sUser %s disconnect on %s", prefix, c_session->user_name, address); break; } return 1; }
void get_device_info(const char *device, DevInfo *devinfo) { glibtop_netload netload; guint8 *hw; g_assert(device); memset(devinfo, 0, sizeof *devinfo); devinfo->name = g_strdup(device); devinfo->type = DEV_UNKNOWN; glibtop_get_netload(&netload, device); devinfo->tx = netload.bytes_out; devinfo->rx = netload.bytes_in; devinfo->up = (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_UP) ? TRUE : FALSE); devinfo->running = (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_RUNNING) ? TRUE : FALSE); devinfo->ip = format_ipv4(netload.address); devinfo->netmask = format_ipv4(netload.subnet); devinfo->ipv6 = format_ipv6(netload.address6); devinfo->qual = 0; devinfo->essid = NULL; hw = netload.hwaddress; if (hw[6] || hw[7]) { devinfo->hwaddr = g_strdup_printf( "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", hw[0], hw[1], hw[2], hw[3], hw[4], hw[5], hw[6], hw[7]); } else { devinfo->hwaddr = g_strdup_printf( "%02X:%02X:%02X:%02X:%02X:%02X", hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]); } /* stolen from gnome-applets/multiload/linux-proc.c */ if(netload.if_flags & (1L << GLIBTOP_IF_FLAGS_LOOPBACK)) { devinfo->type = DEV_LO; } #ifdef HAVE_IW else if (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_WIRELESS)) { devinfo->type = DEV_WIRELESS; get_wireless_info (devinfo); } #endif /* HAVE_IW */ else if(netload.if_flags & (1L << GLIBTOP_IF_FLAGS_POINTOPOINT)) { if (g_str_has_prefix(device, "plip")) { devinfo->type = DEV_PLIP; } else if (g_str_has_prefix(device, "sl")) { devinfo->type = DEV_SLIP; } else { devinfo->type = DEV_PPP; } get_ptp_info(devinfo); } else { devinfo->type = DEV_ETHERNET; } }
/** * This one forgot the treatment of ESTABLISHED and CLOSE case. * */ G_MODULE_EXPORT gint user_packet_logs(void *element, tcp_state_t state, gpointer params) { char *prefix = "[nuauth] "; char *str_state; char source_addr[INET6_ADDRSTRLEN]; char dest_addr[INET6_ADDRSTRLEN]; char *saddr; char *daddr; char *log_prefix = "Default"; u_int16_t sport; u_int16_t dport; /* contruct request */ switch (state) { case TCP_STATE_OPEN: str_state = "Open "; break; case TCP_STATE_CLOSE: str_state = "Close "; break; case TCP_STATE_ESTABLISHED: str_state = "Established "; break; case TCP_STATE_DROP: str_state = "Drop "; break; default: str_state = "Unknown "; } if ((state == TCP_STATE_OPEN) || (state == TCP_STATE_DROP)) { const connection_t *connection = element; /* convert IP source and destination addresses to string */ format_ipv6(&connection->tracking.saddr, source_addr, INET6_ADDRSTRLEN, NULL); format_ipv6(&connection->tracking.daddr, dest_addr, INET6_ADDRSTRLEN, NULL); if (connection->log_prefix) { log_prefix = connection->log_prefix; } saddr = source_addr; daddr = dest_addr; if (((connection->tracking).protocol == IPPROTO_TCP) || ((connection->tracking).protocol == IPPROTO_UDP)) { sport = (connection->tracking).source; dport = (connection->tracking).dest; g_message ("%s%s %s[%s] %ld : IN=%s OUT=%s SRC=%s DST=%s PROTO=%d SPT=%u DPT=%u", prefix, log_prefix, str_state, connection->username, connection->timestamp, connection->iface_nfo.indev, connection->iface_nfo.outdev, saddr, daddr, connection->tracking.protocol, sport, dport); } else { g_message ("%s%s %s[%s] %ld : IN=%s OUT=%s SRC=%s DST=%s PROTO=%d", prefix, log_prefix, str_state, connection->username, connection->timestamp, connection->iface_nfo.indev, connection->iface_nfo.outdev, source_addr, dest_addr, connection->tracking.protocol); } } return 0; }
/** * 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; }
/** * Ask each client of global_msg address set to send their new connections * (connections in stage "SYN SENT"). * * \param global_msg Address set of clients * \return Returns 0 on error, 1 otherwise */ char warn_clients(struct msg_addr_set *global_msg, user_session_check_t *scheck, gpointer data) { ip_sessions_t *ipsessions = NULL; GSList *ipsockets = NULL; struct timeval timestamp; struct timeval interval; #if DEBUG_ENABLE if (DEBUG_OR_NOT(DEBUG_LEVEL_VERBOSE_DEBUG, DEBUG_AREA_USER)) { char addr_ascii[INET6_ADDRSTRLEN]; format_ipv6(&global_msg->addr, addr_ascii, INET6_ADDRSTRLEN, NULL); g_message("Warn client(s) on IP %s", addr_ascii); } #endif lock_client_datas(); ipsessions = g_hash_table_lookup(client_ip_hash, &global_msg->addr); if (ipsessions) { global_msg->found = TRUE; /* if data or scheck is not NULL we need to send the message and thus we do not enter the delay code */ if ((!(data || scheck)) && ipsessions->proto_version >= PROTO_VERSION_V22_1) { gettimeofday(×tamp, NULL); timeval_substract(&interval, ×tamp, &(ipsessions->last_message)); if ((interval.tv_sec == 0) && ((unsigned)interval.tv_usec < nuauthconf->push_delay)) { unlock_client_datas(); return 1; } else { ipsessions->last_message.tv_sec = timestamp.tv_sec; ipsessions->last_message.tv_usec = timestamp.tv_usec; } } for (ipsockets = ipsessions->sessions; ipsockets; ipsockets = ipsockets->next) { user_session_t *session = (user_session_t *)ipsockets->data; if ((!scheck) || scheck(session, data)) { struct msg_addr_set *gmsg = g_memdup(global_msg, sizeof(*global_msg)); gmsg->msg = g_memdup(global_msg->msg, ntohs(global_msg->msg->length)); #if DEBUG_ENABLE if (DEBUG_OR_NOT(DEBUG_LEVEL_VERBOSE_DEBUG, DEBUG_AREA_USER)) { char addr_ascii[INET6_ADDRSTRLEN]; format_ipv6(&global_msg->addr, addr_ascii, INET6_ADDRSTRLEN, NULL); g_message("Queuing message for %s (%d)", addr_ascii, session->socket); } #endif g_async_queue_push(session->workunits_queue, gmsg); if (session->activated) { session->activated = FALSE; g_async_queue_push(writer_queue, GINT_TO_POINTER(session->socket)); ev_async_send(session->srv_context->loop, &session->srv_context->client_writer_signal); } } } unlock_client_datas(); return 1; } else { global_msg->found = FALSE; unlock_client_datas(); return 0; } }