wifidog源码http.c文件分析
来源:互联网 发布:阿秋秋的淘宝店 编辑:程序博客网 时间:2024/06/08 03:04
wifidog源码中的http.c文件,该文件是实现认证和页面跳转操作:
#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <string.h>#include <unistd.h>#include <syslog.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include "httpd.h"#include "safe.h"#include "debug.h"#include "conf.h"#include "auth.h"#include "firewall.h"#include "http.h"#include "client_list.h"#include "common.h"#include "centralserver.h"#include "util.h"#include "wd_util.h"#include "../config.h"/** The 404 handler is also responsible for redirecting to the auth server */void //web页面404操作http_callback_404(httpd * webserver, request * r, int error_code){ char tmp_url[MAX_BUF], *url, *mac; s_config *config = config_get_config(); //获取配置文件中的数据 t_auth_serv *auth_server = get_auth_server(); //连接到服务器, memset(tmp_url, 0, sizeof(tmp_url)); /* * XXX Note the code below assumes that the client's request is a plain * http request to a standard port. At any rate, this handler is called only * if the internet/auth server is down so it's not a huge loss, but still. */ snprintf(tmp_url, (sizeof(tmp_url) - 1), "http://%s%s%s%s", r->request.host, r->request.path, r->request.query[0] ? "?" : "", r->request.query); url = httpdUrlEncode(tmp_url); //对url进程encode操作 if (!is_online()) { //连接不到服务器,服务器状态为down /* The internet connection is down at the moment - apologize and do not redirect anywhere */ char *buf; safe_asprintf(&buf, "<p>We apologize, but it seems that the internet connection that powers this hotspot is temporarily unavailable.</p>" "<p>If at all possible, please notify the owners of this hotspot that the internet connection is out of service.</p>" "<p>The maintainers of this network are aware of this disruption. We hope that this situation will be resolved soon.</p>" "<p>In a while please <a href='%s'>click here</a> to try your request again.</p>", tmp_url); send_http_page(r, "Uh oh! Internet access unavailable!", buf); //发送状态页面及buf信息到客户端 free(buf); debug(LOG_INFO, "Sent %s an apology since I am not online - no point sending them to auth server", r->clientAddr); } else if (!is_auth_online()) { //连接到服务器,但是服务器不提供重定向服务 /* The auth server is down at the moment - apologize and do not redirect anywhere */ char *buf; safe_asprintf(&buf, "<p>We apologize, but it seems that we are currently unable to re-direct you to the login screen.</p>" "<p>The maintainers of this network are aware of this disruption. We hope that this situation will be resolved soon.</p>" "<p>In a couple of minutes please <a href='%s'>click here</a> to try your request again.</p>", tmp_url); send_http_page(r, "Uh oh! Login screen unavailable!", buf); free(buf); debug(LOG_INFO, "Sent %s an apology since auth server not online - no point sending them to auth server", r->clientAddr); } else { //服务器端运行正常,提供重定向服务 /* Re-direct them to auth server */ char *urlFragment; if (!(mac = arp_get(r->clientAddr))) { //获取客户端的mac地址 /* We could not get their MAC address */ debug(LOG_INFO, "Failed to retrieve MAC address for ip %s, so not putting in the login request", r->clientAddr); safe_asprintf(&urlFragment, "%sgw_address=%s&gw_port=%d&gw_id=%s&ip=%s&url=%s", auth_server->authserv_login_script_path_fragment, config->gw_address, config->gw_port, config->gw_id, r->clientAddr, url); } else { debug(LOG_INFO, "Got client MAC address for ip %s: %s", r->clientAddr, mac); safe_asprintf(&urlFragment, "%sgw_address=%s&gw_port=%d&gw_id=%s&ip=%s&mac=%s&url=%s", auth_server->authserv_login_script_path_fragment, config->gw_address, config->gw_port, config->gw_id, r->clientAddr, mac, url); free(mac); } // if host is not in whitelist, maybe not in conf or domain'IP changed, it will go to here. //如果客户端主机不再白名单中,则进行下面的操作 debug(LOG_INFO, "Check host %s is in whitelist or not", r->request.host); // e.g. www.example.com t_firewall_rule *rule; //e.g. example.com is in whitelist // if request http://www.example.com/, it's not equal example.com. for (rule = get_ruleset("global"); rule != NULL; rule = rule->next) { debug(LOG_INFO, "rule mask %s", rule->mask); if (strstr(r->request.host, rule->mask) == NULL) { debug(LOG_INFO, "host %s is not in %s, continue", r->request.host, rule->mask); continue; } //分析客户端主机 int host_length = strlen(r->request.host); int mask_length = strlen(rule->mask); if (host_length != mask_length) { char prefix[1024] = { 0 }; // must be *.example.com, if not have ".", maybe Phishing. e.g. phishingexample.com strncpy(prefix, r->request.host, host_length - mask_length - 1); // e.g. www strcat(prefix, "."); // www. strcat(prefix, rule->mask); // www.example.com if (strcasecmp(r->request.host, prefix) == 0) { debug(LOG_INFO, "allow subdomain"); fw_allow_host(r->request.host); http_send_redirect(r, tmp_url, "allow subdomain"); //执行重定向 free(url); free(urlFragment); return; } } else { // e.g. "example.com" is in conf, so it had been parse to IP and added into "iptables allow" when wifidog start. but then its' A record(IP) changed, it will go to here. debug(LOG_INFO, "allow domain again, because IP changed"); fw_allow_host(r->request.host); http_send_redirect(r, tmp_url, "allow domain"); //执行重定向 free(url); free(urlFragment); return; } } debug(LOG_INFO, "Captured %s requesting [%s] and re-directing them to login page", r->clientAddr, url); http_send_redirect_to_auth(r, urlFragment, "Redirect to login page"); //向服务器端申请重定向的登录页面 free(urlFragment); } free(url);}voidhttp_callback_wifidog(httpd * webserver, request * r) // wifidog callback{ send_http_page(r, "WiFiDog", "Please use the menu to navigate the features of this WiFiDog installation.");}voidhttp_callback_about(httpd * webserver, request * r) // wifidog about { send_http_page(r, "About WiFiDog", "This is WiFiDog version <strong>" VERSION "</strong>");}voidhttp_callback_status(httpd * webserver, request * r) //获取运行状态函数{ const s_config *config = config_get_config(); char *status = NULL; char *buf; if (config->httpdusername && //验证用户,并决定是否授权 (strcmp(config->httpdusername, r->request.authUser) || strcmp(config->httpdpassword, r->request.authPassword))) { debug(LOG_INFO, "Status page requested, forcing authentication"); httpdForceAuthenticate(r, config->httpdrealm); return; } status = get_status_text(); //获取状态数据 safe_asprintf(&buf, "<pre>%s</pre>", status); send_http_page(r, "WiFiDog Status", buf); //发送状态数据 free(buf); free(status);}/** @brief Convenience function to redirect the web browser to the auth server * @param r The request * @param urlFragment The end of the auth server URL to redirect to (the part after path) * @param text The text to include in the redirect header ant the mnual redirect title */void //重定向web browser到服务器函数http_send_redirect_to_auth(request * r, const char *urlFragment, const char *text){ char *protocol = NULL; int port = 80; t_auth_serv *auth_server = get_auth_server(); if (auth_server->authserv_use_ssl) { protocol = "https"; port = auth_server->authserv_ssl_port; } else { protocol = "http"; port = auth_server->authserv_http_port; } char *url = NULL; safe_asprintf(&url, "%s://%s:%d%s%s", protocol, auth_server->authserv_hostname, port, auth_server->authserv_path, urlFragment); http_send_redirect(r, url, text); free(url);}/** @brief Sends a redirect to the web browser * @param r The request * @param url The url to redirect to * @param text The text to include in the redirect header and the manual redirect link title. NULL is acceptable */void //发送重定向信息到客户端http_send_redirect(request * r, const char *url, const char *text){ char *message = NULL; char *header = NULL; char *response = NULL; /* Re-direct them to auth server */ debug(LOG_DEBUG, "Redirecting client browser to %s", url); safe_asprintf(&header, "Location: %s", url); safe_asprintf(&response, "302 %s\n", text ? text : "Redirecting"); httpdSetResponse(r, response); //设置http请求的响应 httpdAddHeader(r, header); //添加http请求头 free(response); free(header); safe_asprintf(&message, "Please <a href='%s'>click here</a>.", url); send_http_page(r, text ? text : "Redirection to message", message); free(message);}voidhttp_callback_auth(httpd * webserver, request * r) //登录授权函数{ t_client *client; httpVar *token; char *mac; httpVar *logout = httpdGetVariableByName(r, "logout"); if ((token = httpdGetVariableByName(r, "token"))) { /* They supplied variable "token" */ if (!(mac = arp_get(r->clientAddr))) { /* We could not get their MAC address */ debug(LOG_ERR, "Failed to retrieve MAC address for ip %s", r->clientAddr); send_http_page(r, "WiFiDog Error", "Failed to retrieve your MAC address"); } else { /* We have their MAC address */ //mac和token对比,并增加到客户列表 LOCK_CLIENT_LIST(); if ((client = client_list_find(r->clientAddr, mac)) == NULL) { debug(LOG_DEBUG, "New client for %s", r->clientAddr); client_list_add(r->clientAddr, mac, token->value); } else if (logout) { logout_client(client); } else { debug(LOG_DEBUG, "Client for %s is already in the client list", client->ip); } UNLOCK_CLIENT_LIST(); if (!logout) { /* applies for case 1 and 3 from above if */ authenticate_client(r); } free(mac); } } else { /* They did not supply variable "token" */ send_http_page(r, "WiFiDog error", "Invalid token"); }}voidhttp_callback_disconnect(httpd * webserver, request * r) //断开服务连接{ const s_config *config = config_get_config(); /* XXX How do you change the status code for the response?? */ httpVar *token = httpdGetVariableByName(r, "token"); httpVar *mac = httpdGetVariableByName(r, "mac"); if (config->httpdusername && (strcmp(config->httpdusername, r->request.authUser) || strcmp(config->httpdpassword, r->request.authPassword))) { debug(LOG_INFO, "Disconnect requested, forcing authentication"); httpdForceAuthenticate(r, config->httpdrealm); return; } if (token && mac) { t_client *client; LOCK_CLIENT_LIST(); client = client_list_find_by_mac(mac->value); if (!client || strcmp(client->token, token->value)) { UNLOCK_CLIENT_LIST(); debug(LOG_INFO, "Disconnect %s with incorrect token %s", mac->value, token->value); httpdOutput(r, "Invalid token for MAC"); return; } //验证用户,查找用户列表,除名 /* TODO: get current firewall counters */ logout_client(client); UNLOCK_CLIENT_LIST(); } else { debug(LOG_INFO, "Disconnect called without both token and MAC given"); httpdOutput(r, "Both the token and MAC need to be specified"); return; } return;}void //对http信息反馈message信息send_http_page(request * r, const char *title, const char *message){ s_config *config = config_get_config(); char *buffer; struct stat stat_info; int fd; ssize_t written; fd = open(config->htmlmsgfile, O_RDONLY); if (fd == -1) { debug(LOG_CRIT, "Failed to open HTML message file %s: %s", config->htmlmsgfile, strerror(errno)); return; } if (fstat(fd, &stat_info) == -1) { debug(LOG_CRIT, "Failed to stat HTML message file: %s", strerror(errno)); close(fd); return; } // Cast from long to unsigned int buffer = (char *)safe_malloc((size_t) stat_info.st_size + 1); written = read(fd, buffer, (size_t) stat_info.st_size); if (written == -1) { debug(LOG_CRIT, "Failed to read HTML message file: %s", strerror(errno)); free(buffer); close(fd); return; } close(fd); buffer[written] = 0; httpdAddVariable(r, "title", title); httpdAddVariable(r, "message", message); httpdAddVariable(r, "nodeID", config->gw_id); httpdOutput(r, buffer); //输出buffer中的web信息到客户端 free(buffer);}
0 0
- wifidog源码http.c文件分析
- wifidog http.c&.h分析
- wifidog源码分析 - wifidog原理
- wifidog 源码初分析
- wifidog 源码简要分析
- wifidog源码分析
- wifidog源码大概分析
- wifidog源码分析
- wifidog源码分析 - 初始化阶段
- wifidog源码分析(一)
- Wifidog Commandline.c&.h分析
- wifidog client_list.c&.h分析
- wifidog conf.c&.h分析
- wifidog safe.c&.h分析
- wifidog util.c&.h分析
- wifidog 源码初分析(1)
- wifidog 源码初分析(2)
- wifidog 源码初分析(3)
- synchronized与static synchronized 的区别
- Google提供的ksoap2-android开发客户端来访问远程Web Service
- MyBatis 配置sql语句输出
- Mac下同时安装多个版本的JDK
- 嵌入式Linux驱动及内核模块问题总结
- wifidog源码http.c文件分析
- windows下tomcat指定命令窗口标题
- HDU1700 Points on Cycle(感觉很重要)
- 管理Xcode中organizer下archives列表
- maven批处理安装jar包(windows方式)
- stringstream读写一行数据
- Java千万不能忘记的基础知识总结(不定时更新)
- iOS中UISearchBar(搜索框)使用总结
- ![响应消息的内容类型 text/html; charset=utf-8 与绑定(text/xml; charset=utf-8)的内容类型不匹配。