/** Authenticates a single client against the central server and returns when done * Alters the firewall rules depending on what the auth server says @param r httpd request struct */ void authenticate_client(request * r) { t_client *client, *tmp; t_authresponse auth_response; char *token; httpVar *var; char *urlFragment = NULL; s_config *config = NULL; t_auth_serv *auth_server = NULL; LOCK_CLIENT_LIST(); client = client_dup(client_list_find_by_ip(r->clientAddr)); UNLOCK_CLIENT_LIST(); if (client == NULL) { debug(LOG_ERR, "authenticate_client(): Could not find client for %s", r->clientAddr); return; } /* Users could try to log in(so there is a valid token in * request) even after they have logged in, try to deal with * this */ if ((var = httpdGetVariableByName(r, "token")) != NULL) { token = safe_strdup(var->value); } else { token = safe_strdup(client->token); } /* * At this point we've released the lock while we do an HTTP request since it could * take multiple seconds to do and the gateway would effectively be frozen if we * kept the lock. */ auth_server_request(&auth_response, REQUEST_TYPE_LOGIN, client->ip, client->mac, token, 0, 0); LOCK_CLIENT_LIST(); /* can't trust the client to still exist after n seconds have passed */ tmp = client_list_find_by_client(client); if (NULL == tmp) { debug(LOG_ERR, "authenticate_client(): Could not find client node for %s (%s)", client->ip, client->mac); UNLOCK_CLIENT_LIST(); client_list_destroy(client); /* Free the cloned client */ free(token); return; } client_list_destroy(client); /* Free the cloned client */ client = tmp; if (strcmp(token, client->token) != 0) { /* If token changed, save it. */ free(client->token); client->token = token; } else { free(token); } /* Prepare some variables we'll need below */ config = config_get_config(); auth_server = get_auth_server(); switch (auth_response.authcode) { case AUTH_ERROR: /* Error talking to central server */ debug(LOG_ERR, "Got ERROR from central server authenticating token %s from %s at %s", client->token, client->ip, client->mac); send_http_page(r, "Error!", "Error: We did not get a valid answer from the central server"); break; case AUTH_DENIED: /* Central server said invalid token */ debug(LOG_INFO, "Got DENIED from central server authenticating token %s from %s at %s - deleting from firewall and redirecting them to denied message", client->token, client->ip, client->mac); fw_deny(client); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_DENIED); http_send_redirect_to_auth(r, urlFragment, "Redirect to denied message"); free(urlFragment); break; case AUTH_VALIDATION: /* They just got validated for X minutes to check their email */ debug(LOG_INFO, "Got VALIDATION from central server authenticating token %s from %s at %s" "- adding to firewall and redirecting them to activate message", client->token, client->ip, client->mac); fw_allow(client, FW_MARK_PROBATION); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_ACTIVATE_ACCOUNT); http_send_redirect_to_auth(r, urlFragment, "Redirect to activate message"); free(urlFragment); break; case AUTH_ALLOWED: /* Logged in successfully as a regular account */ debug(LOG_INFO, "Got ALLOWED from central server authenticating token %s from %s at %s - " "adding to firewall and redirecting them to portal", client->token, client->ip, client->mac); fw_allow(client, FW_MARK_KNOWN); // add by zp debug(LOG_INFO,"goto fw_allow()..."); served_this_session++; safe_asprintf(&urlFragment, "%sgw_id=%s", auth_server->authserv_portal_script_path_fragment, config->gw_id); // modify by zp http_send_redirect_to_auth(r, urlFragment, "Redirect to portal"); //char * text = "advertisement"; //http_send_redirect_to_advertisement(r, urlFragment, text); free(urlFragment); break; case AUTH_VALIDATION_FAILED: /* Client had X minutes to validate account by email and didn't = too late */ debug(LOG_INFO, "Got VALIDATION_FAILED from central server authenticating token %s from %s at %s " "- redirecting them to failed_validation message", client->token, client->ip, client->mac); safe_asprintf(&urlFragment, "%smessage=%s", auth_server->authserv_msg_script_path_fragment, GATEWAY_MESSAGE_ACCOUNT_VALIDATION_FAILED); http_send_redirect_to_auth(r, urlFragment, "Redirect to failed validation message"); free(urlFragment); break; default: debug(LOG_WARNING, "I don't know what the validation code %d means for token %s from %s at %s - sending error message", auth_response.authcode, client->token, client->ip, client->mac); send_http_page(r, "Internal Error", "We can not validate your request at this time"); break; } UNLOCK_CLIENT_LIST(); return; }
/* * Run the chat server */ void server_run(void) { //initialize varaibles to be used throughout this function int sockfd, new_fd; struct exchg_msg in, out; socklen_t sin_size; clientqueue.head = NULL; clientqueue.tail = NULL; clientqueue.count = 0; chatserver.room.chatmsgQ.head = 0; chatserver.room.chatmsgQ.tail = 0; struct sockaddr_in add; //socket function sockfd = socket(AF_INET, SOCK_STREAM, 0); //set up chatserver's address chatserver.address.sin_family = AF_INET; chatserver.address.sin_port = htons(port); chatserver.address.sin_addr.s_addr = htonl(INADDR_ANY); memset(&(chatserver.address.sin_zero), '\0', 8); //bind function bind(sockfd, (struct sockaddr *)&chatserver.address, sizeof(struct sockaddr)); //listen function listen(sockfd, BACKLOG); while (1) { // Listen for new connections // 1. if it is a CMD_CLIENT_JOIN, try to create a new client_thread // 1.1) check whether the room is full or not // 1.2) check whether the username has been used or not // 2. otherwise, return ERR_UNKNOWN_CMD sin_size = sizeof(struct sockaddr_in); //accept function new_fd = accept(sockfd, (struct sockaddr *)&add, &sin_size); //receive function recv(new_fd, &in, sizeof(in), 0); //if it is a CMD_CLIENT_JOIN, try to create a new client_thread if (ntohl(in.instruction) == 100) { //check whether the room is full or not if (clientqueue.count == MAX_ROOM_CLIENT) { out.instruction = htonl(106); out.private_data = htonl(201); send(new_fd, &out, sizeof(out), 0); } //check whether the username has been used or not else if (client_dup(in.content) == 0){ out.instruction = htonl(106); out.private_data = htonl(200); send(new_fd, &out, sizeof(out), 0); } //client can be added else { struct chat_client cli; strcpy(cli.client_name, in.content); cli.socketfd = new_fd; sem_wait(&clientqueue.cq_lock); add_client(&cli); sem_post(&clientqueue.cq_lock); pthread_create(&cli.client_thread, NULL, client_thread_fn, (void *) &cli); } } else { //unknown command out.instruction = htonl(106); out.private_data = htonl(202); //send function send(new_fd, &out, sizeof(out), 0); } } }