busybox_httpd, http, CGI
2013-01-14 17:33 850人阅读 评论(0) 收藏 举报
本文章已收录于:
busybox 的安装 busybox-1.18.5.tar.bz2
make menuconfig # This creates a file called ".config"
make # This creates the "busybox" executable
make install # or make CONFIG_PREFIX=/path/from/root install
You will probably need to make your busybox binary setuid root to ensure all configured applets will work properly.
chmod 4755 ./_install/bin/busybox
***********************************************************************************/
httpd server Haserl
http://haserl.sourceforge.net/manpage.html /***********************************************************************************/
使用选项
$ sudo ./busybox httpd -f // -f 前景模式,可以看打印 // -f == 非daemon()
httpd -p 8080 -h $HOME/public_html
httpd -u www
httpd -p 80 -u 80 -h $PWD -c /etc/httpd.conf -r "Web Server Authentication"
* foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World"
* bar=`httpd -e "<Hello World>"` # encode as "<Hello World>"
配置文件
服务器根目录的设置 home_httpd * H:/serverroot # define the server root. It will override -h
特殊IP的访问控制 deny > allow > deny * 拒绝后也是空白?HTTP 錯誤 403 - 禁止
* A:172.20. # Allow address from 172.20.0.0/16
* D:* # Deny from other IP connections
特殊页面的设置 404不起作用?绝对路径
* E404:/path/e404.html # /path/e404.html is the 404 (not found) error page
* I:index.html # Show index.html when a directory is requested
代理地址转换 * P:/url:[http://]hostname[:port]/new/path
# When /urlXXXXXX is requested, reverse proxy it to http://hostname[:port]/new/pathXXXXXX 目录权限控制
* /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/
server: Http头域中包含"WWW-Authenticate: Basic realm=\".\"\r\n" // 客户端会弹出window链接到IP对话框要求输入用户名密码
client: Authorization: Basic YWFhOmJiYg==\r\n // 输入用户名和密码后,以加密形式送出
httpd 中的权限表: 是按照URL长度从大到小排列的!所以查找时按照最近匹配原则。
文件的执行程序
* .au:audio/basic # additional mime type for audio.au files
* *.php:/path/php # run xxx.php through an interpreter
HTTP协议:
GET:
在请求时将请求的内容添加到URL后, http://192.168.60.129/cgi-bin/xmlPost?Text_Field=ding&Radio_Button=2&Submit=Submit 把问号后的全部记录到环境变量 "QUERY_STRING"
POST:
http://192.168.60.129/cgi-bin/xmlPost 在请求的头域中找内容长度"Content-length:" 记录到环境变量"CONTENT_LENGTH",根据长度从标准输入流中取得POST的内容
fgets(xmlData, dataLen + 1, stdin); // 最多只能读入n-1个字符。读入结束后,系统将自动在最后加'\0',并以str作为函数值返回
xmlData[]: Text_Field=ding&Radio_Button=2&Text_Area=lidan&Submit=Submit
// <input type=submit value=POST> 没有name, 数据中就没有这一项
请求有图片的网页:会发送2次请求
dld:handleIncoming enter(buf = GET /cgi-bin/getPageInfo?deviceInfo.html HTTP/1.1)...
dld:handleIncoming enter(buf = GET /cgiPic/cisco_Logo.gif HTTP/1.1)...
httpd.c 代码流程
1. main():
if (daemon(1, 0) < 0) // nochdir = 0, 进入根目录; noclose = 0, 不输出任何打印!!!
运行成功后,父进程自杀;后续都是子进程的打印以及处理!!!
2. mini_httpd():
父进程循环等待客户端的请求
子1进程将0,1重定向到与客户端通信的socket
并处理请求 handle_incoming_and_exit
3. handle_incoming_and_exit // 分析GET行,解析头域Auth..., 解析URL, 调用CGI或者File
send_cgi_and_exit // CGI的处理:
子2进程将0,1重定向到管道, // dup2(outFd, 1);
CGI程序从toCgi管道中读,写入fromCgi管道 // execv(realpath_buff, argp); 子进程执行CGI程序
父2进程=子1: 0, 1为与客户通信的socket
还有与子2进程通信的2个管道
4. cgi_io_loop_and_exit(与子进程通信的2个管道) // 父2进程处理
读 从0(socket)来的数据, 父进程写到toCgi[1]中 // 子进程从toCgi[0]中读。通过以上子2进程0,1重定向实现!!!
读 从fromCgi[0]中来的数据,父进程写到1(socket)中。 // CGI生成的数据子进程写到fromCgi[1]中。同上!!!
1. 还有客户端的数据时,打开toCgi,准备写入
2. 有需要接受post的数据时,从0读,父写到 toCgi
3. 否则关闭toCgi
4. 从 缓存hdr_ptr 写到 toCgi
5. 从 0 读,保存到缓存
6. 从 fromCgi 读,保存到rbuf,然后写到 1 // 可能加入头域等东东
5. #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
a. 在分析请求的头域中,如果含有 "Authorization:" , 则提取用户名密码进行验证
验证 check_user_passwd : 与配置文件httpd.conf 中的"/file:user:pass"字段 进行比较
b. 验证失败,则发送401 // send_headers_and_exit(HTTP_UNAUTHORIZED)
WWW-Authenticate: Basic realm="SEPC89C1DA3532B"\r\n // server response head中含有此字段,客户端浏览器会弹出window窗口,要求输入密码
6. ME:开启CUCM鉴权流程
ENABLE_FEATURE_HTTPD_BASIC_AUTH
ENABLE_AUTH_TO_CUCM
V:/CGI/Screenshot
7. ME: httpd.conf
U:/CGI/Screenshot:/cgi-bin/screenShot
V:/CGI/Screenshot
httpd.c Q&&A
0. 为什么handle_incoming_and_exit后的打印在控制台跟踪不到呢?
在 mini_httpd 函数中 // 即向0,1中读写的东西,实际都送到了套接字中了,因此后面的打印在控制台屏幕显示不出来,而在抓包工具中的包中!!!
n = accept(server_socket, &fromAddr.u.sa, &fromAddr.len);
if (fork() == 0) {
/* child */
/* Do not reload config on HUP */
signal(SIGHUP, SIG_IGN);
close(server_socket);
xmove_fd(n, 0); // 把 0 标准输入重定向到 打开的套接字,并关闭 n
xdup2(0, 1); // 把 1标准输出重定向到 0.
handle_incoming_and_exit(&fromAddr);
}
0. ENABLE_FEATURE_HTTPD_BASIC_AUTH 默认是打开的,为什么访问网页时没有要求输入密码?
客户端没有送密码 且 配置文件也没有配置 就默认为通过验证。
如何打开输入密码框: 在httpd.conf中加入 /cgi-bin:aaa:bbb,第一次无密码验证失败后,要求输入密码
1. 错误505 不支持的版本 // http/1.1 not ,
2. busybox 中的 getLine() !!!注意好多全局的变量!!!
读头域到buf中,遇到/r/n变为\0, 没有处理完,继续处理,直到读的内容处理都处理完了,才再读
3. 配置文件无P:,为什么会走到ENABLE_FEATURE_HTTPD_PROXY 代理的处理中?
为什么send_cgi_and_exit 中的putenv setenv 有问题,走不下去? // 都是入参相关的变量
局部变量指针等在开头赋值,中间处理到CUCM鉴权,socket通信后,
前面的指针的值莫名其秒的变了:指针不是空,printf后死掉,应该是超长 // strerror buflen=2147439428???
原因: char head_for_cucm_auth[] = {0}; // 竟然没有大小,导致栈空间被踩了,!!!
另外局部数组 不要定义太大了。 // char * 8192
4. 为什么没有-c时,会有错误打印 ?// httpd: config error 'U:/CGI/Execute:/cgi-bin/Execute' in 'httpd.conf'
没有匹配任何一个分支,走到最后就会打印错误
没有 -c, 也没有etc中的,就取当前路径下的httpd.conf 并且修改为 TRY_CURDIR_PARSE ,就走不进 U P
5. 为何配置P不起作用 // #if ENABLE_FEATURE_HTTPD_PROXY 默认打开的
if (flag == FIRST_PARSE && ch == 'P') { //busybox要求第一次/etc/httpd.config(or -c /tmp/test/httpd.conf)才解析配置文件的某些项,我改动时删除了 flag 限制!!!
busybox 中P的链表是从最后一条在表头,倒序,且比较时,按照url_from的长度匹配的方式。
(如果配置了P:/:/cgi-bin/getPageInfo, 导致 / /aaa 可能都匹配同一个) // 我改动为完全匹配
只要配置"/", 代理重入时,就会再次匹配上,从而导致死循环,out of memory!
6. 为什么get可以,Post时,cucm Auth失败,返回500?
因为:收到的字段的顺序是不固定的,取得Authorization: Basic ZGxkOmRsZA==\r\n 后的密码要保存一份,以免被后续的覆盖。
// gcc 编译的,在虚拟机上跑的httpd, IP: 用桥接的 http://10.50.146.14:8080/cgi-bin/test-get?Text_Field=&Submit=Submit
7. httpd:bind: 地址已经被使用
80端口在虚拟机上被其他进程使用了,话机里应该没有使用它的。
netstat -an |grep :80
./busybox httpd -p 8080
8. 为什么执行test-get时,显示的空白
cat -A test-get // 查看 多了回车 ^M
vi 中不可见的 :set ff=unix
vi里面用一个命令(:%s/^m//g)删除即可。
CGI
1. 在httpd 运行的目录下建立目录 cgi-bin and cgiPic,
cgi-bin中放入 可执行文件
cgiPic 中放入 图片 或者 弹出页面
// 可执行文件读取某html文件,此文件中含有图片或者弹出页面, 其存放位置应该相对于 读取他们的可执行文件,而不是包含他们的html文件
eg. <IMG SRC="../cgiPic/cisco_Logo.gif"
2. 网页中的链接使用相对路径
3. 根目录: 默认的根目录是httpd 运行的目录
配置文件:H:/... > -h /usr/...
4. http response head 如果不完整的话,wireShark是跟踪不到服务器回应的包的!!!
6. 仅仅CGI程序的错误会导致“找不到伺服器或 DNS 錯誤”!!!
可能CGI程序挂掉了,webServer停在那里,没有给客户端回应。
7. 头域的区分:每行后面有 /r/n ; 结尾有 /r/n /r/n , 后面是
- 上一篇introduce
- 下一篇线程
busybox 的安装 busybox-1.18.5.tar.bz2
make menuconfig # This creates a file called ".config"
make # This creates the "busybox" executable
make install # or make CONFIG_PREFIX=/path/from/root install
You will probably need to make your busybox binary setuid root to ensure all configured applets will work properly.
chmod 4755 ./_install/bin/busybox
***********************************************************************************/
httpd server Haserl
http://haserl.sourceforge.net/manpage.html /***********************************************************************************/
使用选项
$ sudo ./busybox httpd -f // -f 前景模式,可以看打印 // -f == 非daemon()
httpd -p 8080 -h $HOME/public_html
httpd -u www
httpd -p 80 -u 80 -h $PWD -c /etc/httpd.conf -r "Web Server Authentication"
* foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World"
* bar=`httpd -e "<Hello World>"` # encode as "<Hello World>"
配置文件
服务器根目录的设置 home_httpd * H:/serverroot # define the server root. It will override -h
特殊IP的访问控制 deny > allow > deny * 拒绝后也是空白?HTTP 錯誤 403 - 禁止
* A:172.20. # Allow address from 172.20.0.0/16
* D:* # Deny from other IP connections
特殊页面的设置 404不起作用?绝对路径
* E404:/path/e404.html # /path/e404.html is the 404 (not found) error page
* I:index.html # Show index.html when a directory is requested
代理地址转换 * P:/url:[http://]hostname[:port]/new/path
# When /urlXXXXXX is requested, reverse proxy it to http://hostname[:port]/new/pathXXXXXX 目录权限控制
* /cgi-bin:foo:bar # Require user foo, pwd bar on urls starting with /cgi-bin/
server: Http头域中包含"WWW-Authenticate: Basic realm=\".\"\r\n" // 客户端会弹出window链接到IP对话框要求输入用户名密码
client: Authorization: Basic YWFhOmJiYg==\r\n // 输入用户名和密码后,以加密形式送出
httpd 中的权限表: 是按照URL长度从大到小排列的!所以查找时按照最近匹配原则。
文件的执行程序
* .au:audio/basic # additional mime type for audio.au files
* *.php:/path/php # run xxx.php through an interpreter
HTTP协议:
GET:
在请求时将请求的内容添加到URL后, http://192.168.60.129/cgi-bin/xmlPost?Text_Field=ding&Radio_Button=2&Submit=Submit 把问号后的全部记录到环境变量 "QUERY_STRING"
POST:
http://192.168.60.129/cgi-bin/xmlPost 在请求的头域中找内容长度"Content-length:" 记录到环境变量"CONTENT_LENGTH",根据长度从标准输入流中取得POST的内容
fgets(xmlData, dataLen + 1, stdin); // 最多只能读入n-1个字符。读入结束后,系统将自动在最后加'\0',并以str作为函数值返回
xmlData[]: Text_Field=ding&Radio_Button=2&Text_Area=lidan&Submit=Submit
// <input type=submit value=POST> 没有name, 数据中就没有这一项
请求有图片的网页:会发送2次请求
dld:handleIncoming enter(buf = GET /cgi-bin/getPageInfo?deviceInfo.html HTTP/1.1)...
dld:handleIncoming enter(buf = GET /cgiPic/cisco_Logo.gif HTTP/1.1)...
httpd.c 代码流程
1. main():
if (daemon(1, 0) < 0) // nochdir = 0, 进入根目录; noclose = 0, 不输出任何打印!!!
运行成功后,父进程自杀;后续都是子进程的打印以及处理!!!
2. mini_httpd():
父进程循环等待客户端的请求
子1进程将0,1重定向到与客户端通信的socket
并处理请求 handle_incoming_and_exit
3. handle_incoming_and_exit // 分析GET行,解析头域Auth..., 解析URL, 调用CGI或者File
send_cgi_and_exit // CGI的处理:
子2进程将0,1重定向到管道, // dup2(outFd, 1);
CGI程序从toCgi管道中读,写入fromCgi管道 // execv(realpath_buff, argp); 子进程执行CGI程序
父2进程=子1: 0, 1为与客户通信的socket
还有与子2进程通信的2个管道
4. cgi_io_loop_and_exit(与子进程通信的2个管道) // 父2进程处理
读 从0(socket)来的数据, 父进程写到toCgi[1]中 // 子进程从toCgi[0]中读。通过以上子2进程0,1重定向实现!!!
读 从fromCgi[0]中来的数据,父进程写到1(socket)中。 // CGI生成的数据子进程写到fromCgi[1]中。同上!!!
1. 还有客户端的数据时,打开toCgi,准备写入
2. 有需要接受post的数据时,从0读,父写到 toCgi
3. 否则关闭toCgi
4. 从 缓存hdr_ptr 写到 toCgi
5. 从 0 读,保存到缓存
6. 从 fromCgi 读,保存到rbuf,然后写到 1 // 可能加入头域等东东
5. #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
a. 在分析请求的头域中,如果含有 "Authorization:" , 则提取用户名密码进行验证
验证 check_user_passwd : 与配置文件httpd.conf 中的"/file:user:pass"字段 进行比较
b. 验证失败,则发送401 // send_headers_and_exit(HTTP_UNAUTHORIZED)
WWW-Authenticate: Basic realm="SEPC89C1DA3532B"\r\n // server response head中含有此字段,客户端浏览器会弹出window窗口,要求输入密码
6. ME:开启CUCM鉴权流程
ENABLE_FEATURE_HTTPD_BASIC_AUTH
ENABLE_AUTH_TO_CUCM
V:/CGI/Screenshot
7. ME: httpd.conf
U:/CGI/Screenshot:/cgi-bin/screenShot
V:/CGI/Screenshot
httpd.c Q&&A
0. 为什么handle_incoming_and_exit后的打印在控制台跟踪不到呢?
在 mini_httpd 函数中 // 即向0,1中读写的东西,实际都送到了套接字中了,因此后面的打印在控制台屏幕显示不出来,而在抓包工具中的包中!!!
n = accept(server_socket, &fromAddr.u.sa, &fromAddr.len);
if (fork() == 0) {
/* child */
/* Do not reload config on HUP */
signal(SIGHUP, SIG_IGN);
close(server_socket);
xmove_fd(n, 0); // 把 0 标准输入重定向到 打开的套接字,并关闭 n
xdup2(0, 1); // 把 1标准输出重定向到 0.
handle_incoming_and_exit(&fromAddr);
}
0. ENABLE_FEATURE_HTTPD_BASIC_AUTH 默认是打开的,为什么访问网页时没有要求输入密码?
客户端没有送密码 且 配置文件也没有配置 就默认为通过验证。
如何打开输入密码框: 在httpd.conf中加入 /cgi-bin:aaa:bbb,第一次无密码验证失败后,要求输入密码
1. 错误505 不支持的版本 // http/1.1 not ,
2. busybox 中的 getLine() !!!注意好多全局的变量!!!
读头域到buf中,遇到/r/n变为\0, 没有处理完,继续处理,直到读的内容处理都处理完了,才再读
3. 配置文件无P:,为什么会走到ENABLE_FEATURE_HTTPD_PROXY 代理的处理中?
为什么send_cgi_and_exit 中的putenv setenv 有问题,走不下去? // 都是入参相关的变量
局部变量指针等在开头赋值,中间处理到CUCM鉴权,socket通信后,
前面的指针的值莫名其秒的变了:指针不是空,printf后死掉,应该是超长 // strerror buflen=2147439428???
原因: char head_for_cucm_auth[] = {0}; // 竟然没有大小,导致栈空间被踩了,!!!
另外局部数组 不要定义太大了。 // char * 8192
4. 为什么没有-c时,会有错误打印 ?// httpd: config error 'U:/CGI/Execute:/cgi-bin/Execute' in 'httpd.conf'
没有匹配任何一个分支,走到最后就会打印错误
没有 -c, 也没有etc中的,就取当前路径下的httpd.conf 并且修改为 TRY_CURDIR_PARSE ,就走不进 U P
5. 为何配置P不起作用 // #if ENABLE_FEATURE_HTTPD_PROXY 默认打开的
if (flag == FIRST_PARSE && ch == 'P') { //busybox要求第一次/etc/httpd.config(or -c /tmp/test/httpd.conf)才解析配置文件的某些项,我改动时删除了 flag 限制!!!
busybox 中P的链表是从最后一条在表头,倒序,且比较时,按照url_from的长度匹配的方式。
(如果配置了P:/:/cgi-bin/getPageInfo, 导致 / /aaa 可能都匹配同一个) // 我改动为完全匹配
只要配置"/", 代理重入时,就会再次匹配上,从而导致死循环,out of memory!
6. 为什么get可以,Post时,cucm Auth失败,返回500?
因为:收到的字段的顺序是不固定的,取得Authorization: Basic ZGxkOmRsZA==\r\n 后的密码要保存一份,以免被后续的覆盖。
// gcc 编译的,在虚拟机上跑的httpd, IP: 用桥接的 http://10.50.146.14:8080/cgi-bin/test-get?Text_Field=&Submit=Submit
7. httpd:bind: 地址已经被使用
80端口在虚拟机上被其他进程使用了,话机里应该没有使用它的。
netstat -an |grep :80
./busybox httpd -p 8080
8. 为什么执行test-get时,显示的空白
cat -A test-get // 查看 多了回车 ^M
vi 中不可见的 :set ff=unix
vi里面用一个命令(:%s/^m//g)删除即可。
CGI
1. 在httpd 运行的目录下建立目录 cgi-bin and cgiPic,
cgi-bin中放入 可执行文件
cgiPic 中放入 图片 或者 弹出页面
// 可执行文件读取某html文件,此文件中含有图片或者弹出页面, 其存放位置应该相对于 读取他们的可执行文件,而不是包含他们的html文件
eg. <IMG SRC="../cgiPic/cisco_Logo.gif"
2. 网页中的链接使用相对路径
3. 根目录: 默认的根目录是httpd 运行的目录
配置文件:H:/... > -h /usr/...
4. http response head 如果不完整的话,wireShark是跟踪不到服务器回应的包的!!!
6. 仅仅CGI程序的错误会导致“找不到伺服器或 DNS 錯誤”!!!
可能CGI程序挂掉了,webServer停在那里,没有给客户端回应。
7. 头域的区分:每行后面有 /r/n ; 结尾有 /r/n /r/n , 后面是