busybox_httpd, http, CGI

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 , 後面是 

發佈了27 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章