char * get_trusted_domains_text() { pstr_t *pstr = pstr_new(); s_config *config; t_domain_trusted *domain_trusted = NULL; t_ip_trusted *ip_trusted = NULL; config = config_get_config(); pstr_cat(pstr, "\nTrusted domains and its ip:\n"); LOCK_DOMAIN(); for (domain_trusted = config->domains_trusted; domain_trusted != NULL; domain_trusted = domain_trusted->next) { pstr_append_sprintf(pstr, "\nDomain: %s \n", domain_trusted->domain); for(ip_trusted = domain_trusted->ips_trusted; ip_trusted != NULL; ip_trusted = ip_trusted->next) { pstr_append_sprintf(pstr, " %s \n", ip_trusted->ip); } } UNLOCK_DOMAIN(); return pstr_to_string(pstr); }
static char * get_maclist_text(int which) { pstr_t *pstr = NULL; s_config *config; t_trusted_mac *maclist = NULL; int line = 0; config = config_get_config(); switch(which) { case TRUSTED_MAC: pstr = pstr_new(); maclist = config->trustedmaclist; pstr_cat(pstr, "\nTrusted mac list:\n"); break; case UNTRUSTED_MAC: pstr = pstr_new(); maclist = config->mac_blacklist; pstr_cat(pstr, "\nUntrusted mac list:\n"); break; case ROAM_MAC: pstr = pstr_new(); maclist = config->roam_maclist; pstr_cat(pstr, "\nRoam mac list:\n"); break; default: return NULL; } LOCK_CONFIG(); for (; maclist != NULL; maclist = maclist->next) { pstr_append_sprintf(pstr, " %s ", maclist->mac); line++; if(line == 4) { line = 0; pstr_append_sprintf(pstr, "\n"); } } UNLOCK_CONFIG(); return pstr_to_string(pstr); }
/** * Perform an HTTP request, caller frees both request and response, * NULL returned on error. * @param sockfd Socket to use, already connected * @param req Request to send, fully formatted. * @param wait * @return char Response as a string */ char * http_get_ex(const int sockfd, const char *req, int wait) { ssize_t numbytes; int done, nfds; fd_set readfds; struct timeval timeout; size_t reqlen = strlen(req); char readbuf[MAX_BUF]; char *retval; pstr_t *response = pstr_new(); if (sockfd == -1) { /* Could not connect to server */ debug(LOG_ERR, "Could not open socket to server!"); goto error; } debug(LOG_DEBUG, "Sending HTTP request to auth server: [%s]\n", req); numbytes = send(sockfd, req, reqlen, 0); if (numbytes <= 0) { debug(LOG_ERR, "send failed: %s", strerror(errno)); goto error; } else if ((size_t) numbytes != reqlen) { debug(LOG_ERR, "send failed: only %d bytes out of %d bytes sent!", numbytes, reqlen); goto error; } debug(LOG_DEBUG, "Reading response timeout [%d]", wait); done = 0; do { FD_ZERO(&readfds); FD_SET(sockfd, &readfds); timeout.tv_sec = wait; /* XXX magic... 30 second is as good a timeout as any */ timeout.tv_usec = 0; nfds = sockfd + 1; nfds = select(nfds, &readfds, NULL, NULL, &timeout); if (nfds > 0) { /** We don't have to use FD_ISSET() because there * was only one fd. */ memset(readbuf, 0, MAX_BUF); numbytes = read(sockfd, readbuf, MAX_BUF - 1); if (numbytes < 0) { debug(LOG_ERR, "An error occurred while reading from server: %s", strerror(errno)); goto error; } else if (numbytes == 0) { done = 1; } else { readbuf[numbytes] = '\0'; pstr_cat(response, readbuf); debug(LOG_DEBUG, "Read %d bytes", numbytes); if(numbytes < MAX_BUF - 1) done = 1; } } else if (nfds == 0) { debug(LOG_ERR, "Timed out reading data via select() from auth server"); goto error; } else if (nfds < 0) { debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno)); goto error; } } while (!done); close(sockfd); retval = pstr_to_string(response); debug(LOG_DEBUG, "HTTP Response from Server: [%s]", retval); return retval; error: if (sockfd >= 0) { close(sockfd); } retval = pstr_to_string(response); free(retval); return NULL; }
/** * Perform an HTTPS request, caller frees both request and response, * NULL returned on error. * @param sockfd Socket to use, already connected * @param req Request to send, fully formatted. * @param hostname Hostname to use in https request. Caller frees. * @return char Response as a string */ char * https_get(const int sockfd, const char *req, const char *hostname) { ssize_t numbytes; int done, nfds; fd_set readfds; struct timeval timeout; unsigned long sslerr; char sslerrmsg[CYASSL_MAX_ERROR_SZ]; size_t reqlen = strlen(req); char readbuf[MAX_BUF]; char *retval; pstr_t *response = pstr_new(); CYASSL *ssl = NULL; CYASSL_CTX *ctx = NULL; s_config *config; config = config_get_config(); ctx = get_cyassl_ctx(hostname); if (NULL == ctx) { debug(LOG_ERR, "Could not get CyaSSL Context!"); goto error; } if (sockfd == -1) { /* Could not connect to server */ debug(LOG_ERR, "Could not open socket to server!"); goto error; } /* Create CYASSL object */ if ((ssl = CyaSSL_new(ctx)) == NULL) { debug(LOG_ERR, "Could not create CyaSSL context."); goto error; } if (config->ssl_verify) { // Turn on domain name check // Loading of CA certificates and verification of remote host name // go hand in hand - one is useless without the other. CyaSSL_check_domain_name(ssl, hostname); } CyaSSL_set_fd(ssl, sockfd); debug(LOG_DEBUG, "Sending HTTPS request to auth server: [%s]\n", req); numbytes = CyaSSL_send(ssl, req, (int)reqlen, 0); if (numbytes <= 0) { sslerr = (unsigned long)CyaSSL_get_error(ssl, numbytes); CyaSSL_ERR_error_string(sslerr, sslerrmsg); debug(LOG_ERR, "CyaSSL_send failed: %s", sslerrmsg); goto error; } else if ((size_t) numbytes != reqlen) { debug(LOG_ERR, "CyaSSL_send failed: only %d bytes out of %d bytes sent!", numbytes, reqlen); goto error; } debug(LOG_DEBUG, "Reading response"); done = 0; do { FD_ZERO(&readfds); FD_SET(sockfd, &readfds); timeout.tv_sec = 30; /* XXX magic... 30 second is as good a timeout as any */ timeout.tv_usec = 0; nfds = sockfd + 1; nfds = select(nfds, &readfds, NULL, NULL, &timeout); if (nfds > 0) { /** We don't have to use FD_ISSET() because there * was only one fd. */ memset(readbuf, 0, MAX_BUF); numbytes = CyaSSL_read(ssl, readbuf, MAX_BUF - 1); if (numbytes < 0) { sslerr = (unsigned long)CyaSSL_get_error(ssl, numbytes); CyaSSL_ERR_error_string(sslerr, sslerrmsg); debug(LOG_ERR, "An error occurred while reading from server: %s", sslerrmsg); goto error; } else if (numbytes == 0) { /* CyaSSL_read returns 0 on a clean shutdown or if the peer closed the connection. We can't distinguish between these cases right now. */ done = 1; } else { readbuf[numbytes] = '\0'; pstr_cat(response, readbuf); debug(LOG_DEBUG, "Read %d bytes", numbytes); } } else if (nfds == 0) { debug(LOG_ERR, "Timed out reading data via select() from auth server"); goto error; } else if (nfds < 0) { debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno)); goto error; } } while (!done); close(sockfd); CyaSSL_free(ssl); retval = pstr_to_string(response); debug(LOG_DEBUG, "HTTPS Response from Server: [%s]", retval); return retval; error: if (ssl) { CyaSSL_free(ssl); } if (sockfd >= 0) { close(sockfd); } retval = pstr_to_string(response); free(retval); return NULL; }
/* * @return A string containing human-readable status text. MUST BE free()d by caller */ char * get_status_text() { pstr_t *pstr = pstr_new(); s_config *config; t_auth_serv *auth_server; t_client *sublist, *current; int count; time_t uptime = 0; unsigned int days = 0, hours = 0, minutes = 0, seconds = 0; t_trusted_mac *p; t_offline_client *oc_list; pstr_cat(pstr, "WiFiDog status\n\n"); uptime = time(NULL) - started_time; days = (unsigned int)uptime / (24 * 60 * 60); uptime -= days * (24 * 60 * 60); hours = (unsigned int)uptime / (60 * 60); uptime -= hours * (60 * 60); minutes = (unsigned int)uptime / 60; uptime -= minutes * 60; seconds = (unsigned int)uptime; pstr_cat(pstr, "Version: " VERSION "\n"); pstr_append_sprintf(pstr, "Uptime: %ud %uh %um %us\n", days, hours, minutes, seconds); pstr_cat(pstr, "Has been restarted: "); if (restart_orig_pid) { pstr_append_sprintf(pstr, "yes (from PID %d)\n", restart_orig_pid); } else { pstr_cat(pstr, "no\n"); } pstr_append_sprintf(pstr, "Internet Connectivity: %s\n", (is_online()? "yes" : "no")); pstr_append_sprintf(pstr, "Auth server reachable: %s\n", (is_auth_online()? "yes" : "no")); pstr_append_sprintf(pstr, "Clients served this session: %lu\n\n", served_this_session); LOCK_CLIENT_LIST(); count = client_list_dup(&sublist); UNLOCK_CLIENT_LIST(); current = sublist; pstr_append_sprintf(pstr, "%d clients " "connected.\n", count); count = 1; while (current != NULL) { pstr_append_sprintf(pstr, "\nClient %d status [%d]\n", count, current->is_online); pstr_append_sprintf(pstr, " IP: %s MAC: %s\n", current->ip, current->mac); pstr_append_sprintf(pstr, " Token: %s\n", current->token); pstr_append_sprintf(pstr, " First Login: %lld\n", (long long)current->first_login); pstr_append_sprintf(pstr, " Name: %s\n", current->name != NULL?current->name:"null"); pstr_append_sprintf(pstr, " Downloaded: %llu\n Uploaded: %llu\n", current->counters.incoming, current->counters.outgoing); count++; current = current->next; } client_list_destroy(sublist); LOCK_OFFLINE_CLIENT_LIST(); pstr_append_sprintf(pstr, "%d clients " "unconnected.\n", offline_client_number()); oc_list = client_get_first_offline_client(); while(oc_list != NULL) { pstr_append_sprintf(pstr, " IP: %s MAC: %s Last Login: %lld Hit Counts: %d Client Type: %d Temp Passed: %d\n", oc_list->ip, oc_list->mac, (long long)oc_list->last_login, oc_list->hit_counts, oc_list->client_type, oc_list->temp_passed); oc_list = oc_list->next; } UNLOCK_OFFLINE_CLIENT_LIST(); config = config_get_config(); LOCK_CONFIG(); if (config->trustedmaclist != NULL) { pstr_cat(pstr, "\nTrusted MAC addresses:\n"); for (p = config->trustedmaclist; p != NULL; p = p->next) { pstr_append_sprintf(pstr, " %s\n", p->mac); } } pstr_cat(pstr, "\nAuthentication servers:\n"); for (auth_server = config->auth_servers; auth_server != NULL; auth_server = auth_server->next) { pstr_append_sprintf(pstr, " Host: %s (%s)\n", auth_server->authserv_hostname, auth_server->last_ip); } UNLOCK_CONFIG(); return pstr_to_string(pstr); }