ITKeyword,专注技术干货聚合推荐

注册 | 登录

busybox_httpd, http, CGI

分享于 2013-01-14

推荐:Nginx HTTP Server + PHP5 (With fast-cgi And xcache) On Ubuntu Feisty Fawn

http://www.howtoforge.com/nginx_php5_fast_cgi_xcache_ubuntu7.04 

2020腾讯云“6.18”活动开始了!!!(巨大优惠重现!4核8G,5M带宽 1999元/3年),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1059

2020阿里云最低价产品入口,含代金券(新老用户有优惠),
地址https://www.aliyun.com/minisite/goods

busybox_httpd, http, CGI 2013-01-14 17:33 850人阅读 评论(0) 收藏 举报 本文章已收录于: 分类: VOIP (3) 作者同类文章 X 版权声明:本文为博主原创文章,未经博主允许不得转载。 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 "&#60Hello&#32World&#62"

配置文件

服务器根目录的设置 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 "&#60Hello&#32World&#62"

配置文件

服务器根目录的设置 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 , 后面是 

推荐:HTTP 错误 404.2 - Not Found 由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面

    在发布系统的过程中,曾经遇到过这样的问题,由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法 提供您请求的页面。 错误详情如下:   解决方法: 找到

busybox_httpd, http, CGI 2013-01-14 17:33 850人阅读 评论(0) 收藏 举报 本文章已收录于: 分类: VOIP (3) 作者同类文章 X 版权声明:本文为博主原创文章,未经博主允许不得转载。 busybox

相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。