示例#1
0
文件: auth.c 项目: zombie9080/wifi
/** 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);
		}
    }
}