2008年3月26日星期三

最小化安装 Ubuntu

最小化安装 Ubuntu

2007-01-06 Toy Posted in Tutorials, Featured PostRSSTrackback

Ubuntu 的默认安装方式或许并不为所有用户所接受。譬如说吧,有的用户并不想使用 GNOME 桌面环境,也有的用户并不需要预先安装的所有软件。为了解决上述诸如此类的问题,在安装最小化的 Ubuntu 的基础上,根据各人之喜好执行定制化安装,可能是较好的折中方案。

在安装之前需要确定的一件事情是,如何选择安装 CD。根据本文的要求,下载 Alternate install CD 是比较适合的。为了便于安装,应该将下载后的 ISO 文件烧录成光盘。

首先,安装 Ubuntu 基本系统。以 Ubuntu 6.10 为例,当插入安装盘后,计算机从光盘引导系统,这时在初始安装菜单中选择"Install a command-line system",之后与一般的安装过程并无二致。

在基本系统安装完成后,会要求重新启动一次系统,使用在安装过程中设置的帐号及密码登录。

现在,执行指令 sudo vim /etc/apt/sources.list,以便对 sources.list 文件进行编辑。在 VIM 打开文件后,将 deb http:// 或 deb-src http:// 前面包含的注释符号(#)删除。然后保存所作的修改。

为了完成后续的安装过程,需要继续执行指令 sudo apt-get update。

至此,最小化的 Ubuntu 安装已经就绪。

如果需要安装桌面环境,那么还可以执行以下的选择:

   1. 安装 X 窗口系统:sudo apt-get install x-window-system-core。
   2. 安装登录管理器:sudo apt-get install xdm/gdm/kdm[注]。最常见的图形化登录管理器包括 XDM、GDM、KDM,用户可根据自己的需要选择其中之一。
   3. 安装桌面环境或窗口管理器:sudo apt-get install ubuntu-desktop/kubuntu-desktop/xubuntu-desktop。这将分别安装 GNOME、KDE、XFCE 桌面环境。对于 GNOME、KDE、XFCE 这些桌面环境来说,为了获得更强的定制效果,也可仅安装最基本的组件,如:sudo apt-get install gnome-core/kde-core/xfce4。当然,如果不需要桌面环境,也可选择安装窗口管理器代替。那样的话,可以执行指令 sudo apt-get install fluxbox/icewm/enlightenment/fvwm。
   4. 安装软件:sudo apt-get install firefox/gaim/xmms。这将安装 Firefox 浏览器、Gaim 聊天程序、XMMS 音乐播放器。同样,不必拘泥于此处的示例,完全可以按自己的喜好来安装。

一旦完成上述过程的安装,重启系统,将会享受到一个完全自由的系统。

注释

类似 xdm/gdm/kdm 这样的写法需要读者选择其中一项才能无误地执行命令。

安装xorg最好使用sudo aptitude xserver-xorg,用apt-get install的话生成xorg.conf时有问题。
edgy里面好像不是这个,我看了一下老外的做法,用的是sudo apt-get install xserver-xorg -y,我试了,好使
--
6G免费网络U盘: http://www.orbitfiles.com/signup/rleon

2008年3月25日星期二

~/.Xresources中关于urxvt的配置部分


! urxvt color set
URxvt.background:black
URxvt.foreground:green
URxvt.colorBD:yellow
URxvt.colorUL:Green
URxvt.color0: #000000
URxvt.color1: #CC0000
URxvt.color2: #4E9A06
URxvt.color3: #C4A000
URxvt.color4: #3465A4
URxvt.color5: #75507B
URxvt.color6: #06989A
URxvt.color7: #D3D7CF
URxvt.color8: #555753
URxvt.color9: #EF2929
URxvt.color10: #8AE234
URxvt.color11: #FCE94F
URxvt.color12: #729FCF
URxvt.color13: #AD7FA8
URxvt.color14: #34E2E2
URxvt.color15: #EEEEEC

! scroll set
URxvt.scrollBar:false
!URxvt.scrollBar_right:True
!URxvt.scrollBar_floating:True
!URxvt.scrollstyle:plain
!URxvt.scrollWithBuffer:false
URxvt.saveLines:5000

! font set
URxvt.font:xft:Liberation Mono:pixelsize=16:antialias=false,xft:Microsoft Yahei:pixelsize=18
URxvt.boldFont:xft:Liberation Mono:pixelsize=16:antialias=false:Bold,xft:Microsoft Yahei:pixelsize=18:Bold

! Input Method set
!URxvt.inputMethod:fcitx
!URxvt.imFont:Liberation Mono
!URxvt.preeditType: Root

! window geometry set
URxvt.geometry: 80x30
URxvt.title:Rxvt-Unicode

! bg transparent set
!URxvt.inheritPixmap: true
!URxvt.tintCddolor: white
!URxvt.shading: 80

! Tab set
!URxvt.perl-ext-common: default,tabbed
!URxvt.tabbed.tab-fg: 12
!URxvt.tabbed.tab-bg: 0
!URxvt.tabbed.tabbar-fg: 4

!Rxvt.menu:/etc/X11/rxvt.menu
!Rxvt.preeditType:Root
!Rxvt.transparency:255

! 开启标签功能
URxvt.perl-ext-common: default,tabbed


2008年2月28日星期四

宝宝顽皮

宝宝太顽皮了,现在是基本上没有停的可能。以前是盼着他长大,会走路,那样自己不用抱着他晒太阳,轻松呀。现在倒好,出去玩的时候是轻松了,可以在家里的时候可不得了了。把抽屉里够得到的都扔出来,现在可以从小板凳爬上大板凳,然后上桌子,最后上房揭瓦。看什么都新鲜,玩够了就扔地上,家里已经基本上没有可以干净的了,全是扔得乱七八糟的。

有次玩两衣服夹子,把它们都夹住了自己的嘴,然后痛,但又哭不了,张不开嘴,哈哈

--
6G免费网络U盘: http://www.orbitfiles.com/signup/rleon

2007年11月4日星期日

一个测试procmailrc的脚本

在你的测试目录(/home/myid/test,可以改)下建proctest.rc作为procmailrc文件,邮件文件为mail.msg(只包含一个邮件),直接运行proctest就可以了
 
#!/bin/sh
#The executable file named "proctest"
#
# You need a test directory.
TESTDIR=/home/myid/test
if [ ! -d ${TESTDIR} ] ; then
  echo "Directory ${TESTDIR} does not exist; First create it"
  exit 0
fi
#
#Feed an email message to procmail. Apply proctest.rc recipes file.
#First prepare a mail.msg email file which you wish to use for the
#testing.
procmail ${TESTDIR}/proctest.rc < mail.msg
#
#Show the results.
less ${TESTDIR}/Proctest.log
clear
less ${TESTDIR}/Proctest.mail
#
#Clean up.
rm -i ${TESTDIR}/Proctest.log
rm -i ${TESTDIR}/Proctest.mail
 
下面是一个简单的procmailrc的例子proctest.rc
 
SHELL=/bin/sh TESTDIR=/home/myid/test MAILDIR=${TESTDIR} LOGFILE=${TESTDIR}/Proctest.log LOG="--- Logging for ${LOGNAME}, "  #Troubleshooting: VERBOSE=yes LOGABSTRACT=all  #Let's test stripping lines from the email message's header :0 fwh | egrep -vi "(^Content-|^MIME-Version:.)"  #If it is from myself, store the email message :0: * $ ^From:.*${LOGNAME} ${TESTDIR}/Proctest.mail  #Otherwise, discard the email message :0 /dev/null 


--
一步一步教你从互联网赚钱 http://www.zqzn.com/index.asp?rid=key480769
投资理财 http://li-cai.blogspot.com/

procmailrc examples

 
email MIME/QP decode
取名� /etc/parser_subj   (mode 755)

#!/usr/bin/perl
    $sub=join(" ",@ARGV);
    if ($sub=~ /=\?\S+\?\l(\S)\?/) {
      if ($1 =~ /[Qq]/) {
        $sub=decode_qp($sub);
      }
      elsif ($1 =~ /[Bb]/) {
        $sub=decode_base64($sub);
      }
    }
    elsif ($sub=~ /=[a-fA-F0-9][a-fA-F0-9]/) {
      $sub=decode_qp($sub);
    }
    $subject.=$sub;
    $subject=~s/\'/\\\'/g;
    $subject=~s/\"/\\\"/g;
print $subject;
sub decode_qp {
        my($string) = @_;
        @buffer=split(/\?/,$string);
        $string = $buffer[3] if ($buffer[3] ne "");
        $string =~ s/=([\da-fA-F]{2})/pack("C", hex($1))/ge;
        $string =~ /\?=(.*)/;
        $string =~ tr/_/ /;
        $buffer[4]=~s/^=//;
        $buffer[0]=~s/=$//;
        $string="$buffer[0]$string$buffer[4]";
        return($string);
}

sub decode_base64 {
        my($string) = @_;
        my($string2);
        @buffer=split(/\?/,$string);
        $string = $buffer[3] if ($buffer[3] ne "");
        $string =~ s/=+$//;
        $string =~ tr|A-Za-z0-9+/| -_|;
        while($string =~ /(.{1,60})/gs) {
                my($string3) = chr(32+length($1)*3/4);
                $string2 .= unpack("u",$string3 . $1 );
        }
        $buffer[4]=~s/^=//;
        $buffer[0]=~s/=$//;
        $string2="$buffer[0]$string2$buffer[4]";
        return($string2);
}



在 procmail 中加入:

LOGABSTRACT=all
LOGFILE=/tmp/procmail.log
tmp=`formail -I "" | sed -e '/Content-Type/,/^$/!d' | grep "filename=" | sed -e 's/.*filename\=\(.*\)\?.*/\1/g'`
ATTACH=`/etc/parser_subj $tmp`

:0
....��你自己去�吧...自己做�功�就�了


去看 /tmp/procmail.log 中的�西,就知道用意了
PATH=$PATH
SHELL=/bin/sh
MAILDIR=/var/spool/mail
VERBOSE=yes
LOGABSTRACT=all
SENDMAIL=/usr/sbin/sendmail
LOGFILE=$HOME/procmail/procmail.log
FILE=`echo $HOME`/procmail/mail_folder/mail-`date +%Y%m%d%H%I%S`-`echo $$`.eml
tmp=`formail >; $FILE; chmod 644 $FILE`
tmp=`formail -zxSubject:`
SUBJ=`/etc/parser_subj "$tmp"| sed -e "s/[\$,\(,\),\',\\]//g"`
FROM=`formail -zxFrom:| sed -e 's/.*<\(.*\)>;.*/\1/g'`
SPAMID=`formail -I ""|grep '/sc?id=' | sed -e 's/.*id=\(.*\)/\1/g'`
PTR=`formail -zxReceived:|grep ^from|sed -e 's/.*\[\(.*\)\.\(.*\)\.\(.*\)\.\(.*\)\].*/\4.\3.\2.\1/g'|head -1`
MYSQL="mysql -h procmail.mydomain.net.tw -u abel -pxxxxxxxx procmail"

# ���取回�的信不再��
:0 H
* ^X-resend:
/var/spool/mail/$LOGNAME


# 白名��理
WHITE_LIST=`echo "SELECT WHITE_NAME FROM WHITE_LIST WHERE USERNAME='$LOGNAME' AND instr('$FROM', WHITE_NAME ) or instr('$SUBJ', WHITE_NAME )"| $MYSQL |  tr '\n' '|' ; echo "aaaaaaaazzzzzzzzzggggggggg"`

:0 H

* $($WHITE_LIST)

$ORGMAIL



# �?#125;中巳�有 SPAM

:0 HD

* ^Subject: SPAM.*

{

        :0 fw

        | ( echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','SPAM','�?#125; SPAM')"    | $MYSQL)



        :0

        /dev/null

}



# �信不�自己�位但  Message-ID �自己

:0 HD

* !^From: .*@mydomain.net.tw.*

* !^Received: .*211\.72\.21[0-1]\..*

* ^Message-Id: .*@mydomain.net.*

{

:0 fw

| echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','�信��','Message-ID � mydomain')"    | $MYSQL



:0

/dev/null

}



# spamcop 的��信回函�存 mysql, 再以程式去 submit form

:0 H

* ^Subject: .*SpamCop has accepted.*

{

        :0 fw

        | ( echo "insert into SPAMCOP_ID(SPAM_ID) values('$SPAMID')" | $MYSQL)



        :0

        /dev/null

}



# 一些大的�告信商

:0 HD

* (^From:|^Received:|Return-Path:) .*(mailserver.idv.tw|mailserver.com|worldad.net|mailnews.com.tw|rayman.com.cn).*

{

:0 fw

| echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','�信��','mailserver 信商�出')"    | $MYSQL



:0

/dev/null

}





# 收信人��字型�

:0 HD

* ^To: .*[0-9][0-9].txt.*

{

:0 fw

| echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','�信��','�字型收件者')"    | $MYSQL



:0

/dev/null

}



# From: user@mydomain.net.tw 但不�自己人

:0 HD

* ^From: .*@mydomain.net.tw.*

* !^Received: .*211\.72\.21[0-1]\..*

{

:0 fw

| (username=${FROM%%@*};if [ -d /home/$username ] ; then formail -A "Bogus: No"; else formail -A "Bogus: Yes";  echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','寄件人不存在','$FROM ')" | $MYSQL ;fi  );



:0 

* ^Bogus: Yes

/dev/null

}





# 主旨��,�料存?mysql

:0 HD

* ! ^From: .*@mydomain.net.tw.*

{

patten=`echo "select concat(\"'\",PATTEN,\"'\") from SPAM_PATTEN where USERNAME='$LOGNAME' and instr('$SUBJ',PATTEN)"|$MYSQL | grep -v 'PATTEN'| tr '\n' ','`

patten2=`echo $patten | sed -e "s/'//g"`



        :0 fw

* ? test -n "$patten"

        | ( formail -A "Spam: $patten" ; \

echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','符合特定字串','$patten2'); update SPAM_PATTEN set CNT=CNT+1 where USERNAME='$LOGNAME' and PATTEN in ($patten ''); " | $MYSQL ;\

)



        :0

        * ^Spam: .*

        /dev/null

}



# RBL ��, rbl doamin 存於 mysql

:0 

* ! ^From: .*@(mydomain.net.tw|mydomain.net).*

* ! ^Received: .*159\.226\.*

{

rbl=`for spam in $(echo "select RBL_DOMAIN from SPAM_SOURCE order by SN"| $MYSQL | grep -v 'RBL_DOMAIN'); do  rbl=$(host $PTR.$spam| grep 'has address'); test -n "$rbl" && echo $PTR.$spam && break; done`



        :0 fw

|( test -n "$rbl" && (echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','�自 RBL IP','$rbl.$spam')" | $MYSQL) && formail -A "Spam: From_RBL $rbl.$spam" )



        :0

        * ^Spam: .*

        /dev/null

}
�果呈�:
http://211.72.210.251/spamcop.html
 
2007-11-04

r01ustc

2007年11月3日星期六

使用 OpenSSL API 进行安全编程


OpenSSL API 的文档有些含糊不清。因为还没有多少关于 OpenSSL 使用的教程,所以对初学者来说,在应用程序中使用它可能会有一些困难。那么怎样才能使用 OpenSSL 实现一个基本的安全连接呢?本教程将帮助您解决这个问题。

学习如何实现 OpenSSL 的困难部分在于其文档的不完全。不完全的 API 文档通常会妨碍开发人员使用该 API,而这通常意味着它注定要失败。但 OpenSSL 仍然很活跃,而且正逐渐变得强大。这是为什么?

OpenSSL 是用于安全通信的最著名的开放库。在 google 中搜索"SSL library"得到的返回结果中,列表最上方就是 OpenSSL。它诞生于 1998 年,源自 Eric Young 和 Tim Hudson 开发的 SSLeay 库。其他 SSL 工具包包括遵循 GNU General Public License 发行的 GNU TLS,以及 Mozilla Network Security Services(NSS)(请参阅本文后面的 参考资料 ,以获得其他信息)。

那么,是什么使得 OpenSSL 比 GNU TLS、Mozilla NSS 或其他所有的库都优越呢?许可是一方面因素(请参阅 参考资料)。此外,GNS TLS(迄今为止)只支持 TLS v1.0 和 SSL v3.0 协议,仅此而已。

Mozilla NSS 的发行既遵循 Mozilla Public License 又遵循 GNU GPL,它允许开发人员进行选择。不过,Mozilla NSS 比 OpenSSL 大,并且需要其他外部库来对库进行编译,而 OpenSSL 是完全自包含的。与 OpenSSL 相同,大部分 NSS API 也没有文档资料。Mozilla NSS 获得了 PKCS #11 支持,该支持可以用于诸如智能卡这样的加密标志。OpenSSL 就不具备这一支持。

先决条件

要充分理解并利用本文,您应该:

  • 精通 C 编程。
  • 熟悉 Internet 通信和支持 Internet 的应用程序的编写。

并不绝对要求您熟悉 SSL ,因为稍后将给出对 SLL 的简短说明;不过,如果您希望得到详细论述 SSL 的文章的链接,请参阅 参考资料部分。拥有密码学方面的知识固然好,但这并不是必需的。





回页首


什么是 SSL?

SSL 是一个缩写,代表的是 Secure Sockets Layer。它是支持在 Internet 上进行安全通信的标准,并且将数据密码术集成到了协议之中。数据在离开您的计算机之前就已经被加密,然后只有到达它预定的目标后才被解密。证书和密码学算法支持了这一切的运转,使用 OpenSSL,您将有机会切身体会它们。

理论上,如果加密的数据在到达目标之前被截取或窃听,那些数据是不可能被破解的。不过,由于计算机的变化一年比一年快,而且密码翻译方法有了新的发展,因此,SSL 中使用的加密协议被破解的可能性也在增大。

可以将 SSL 和安全连接用于 Internet 上任何类型的协议,不管是 HTTP、POP3,还是 FTP。还可以用 SSL 来保护 Telnet 会话。虽然可以用 SSL 保护任何连接,但是不必对每一类连接都使用 SSL。如果连接传输敏感信息,则应使用 SSL。





回页首


什么是 OpenSSL?

OpenSSL 不仅仅是 SSL。它可以实现消息摘要、文件的加密和解密、数字证书、数字签名和随机数字。关于 OpenSSL 库的内容非常多,远不是一篇文章可以容纳的。

OpenSSL 不只是 API,它还是一个命令行工具。命令行工具可以完成与 API 同样的工作,而且更进一步,可以测试 SSL 服务器和客户机。它还让开发人员对 OpenSSL 的能力有一个认识。要获得关于如何使用 OpenSSL 命令行工具的资料,请参阅 参考资料部分。





回页首


您需要什么

首先需要的是最新版本的 OpenSSL。查阅参考资料部分,以确定从哪里可以获得最新的可以自己编译的源代码,或者最新版本的二进制文件(如果您不希望花费时间来编译的话)。不过,为了安全起见,我建议您下载最新的源代码并自己编译它。二进制版本通常是由第三方而不是由 OpenSSL 的开发人员来编译和发行的。

一些 Linux 的发行版本附带了 OpenSSL 的二进制版本,对于学习如何使用 OpenSSL 库来说,这足够了;不过,如果您打算去做一些实际的事情,那么一定要得到最新的版本,并保持该版本一直是最新的。

对于以 RPM 形式安装的 Linux 发行版本(Red Hat、Mandrake 等),建议您通过从发行版本制造商那里获得 RPM 程序包来更新您的 OpenSSL 发行版本。出于安全方面的原因,建议您使用最新版本的发行版本。如果您的发行版本不能使用最新版本的 OpenSSL,那么建议您只覆盖库文件,不要覆盖可执行文件。OpenSSL 附带的 FAQ 文档中包含了有关这方面的细节。

还要注意的是,OpenSSL 并没有在所有的平台上都获得官方支持。虽然制造商已经尽力使其能够跨平台兼容,但仍然存在 OpenSSL 不能用于您的计算机 和/或 操作系统的可能。请参阅 OpenSSL 的 Web 站点( 参考资料 中的链接),以获得关于哪些平台可以得到支持的信息。

如果想使用 OpenSSL 来生成证书请求和数字证书,那么必须创建一个配置文件。在 OpenSSL 程序包的 apps 文件夹中,有一个名为 openssl.cnf 的可用模板文件。我不会对该文件进行讨论,因为这不在本文要求范围之内。不过,该模板文件有一些非常好的注释,而且如果在 Internet 上搜索,您可以找到很多讨论修改该文件的教程。





回页首


头文件和初始化

本教程所使用的头文件只有三个:ssl.h、bio.h 和 err.h。它们都位于 openssl 子目录中,而且都是开发您的项目所必需的。要初始化 OpenSSL 库,只需要三个代码行即可。清单 1 中列出了所有内容。其他的头文件 和/或 初始化函数可能是其他一些功能所必需的。


清单 1. 必需的头文件
/* OpenSSL headers */  #include "openssl/bio.h"  #include "openssl/ssl.h"  #include "openssl/err.h"  /* Initializing OpenSSL */  SSL_load_error_strings();  ERR_load_BIO_strings();  OpenSSL_add_all_algorithms();  





回页首


建立非安全连接

不管连接是安全的还是不安全的,OpenSSL 都使用了一个名为 BIO 的抽象库来处理包括文件和套接字在内的各种类型的通信。您还可以将 OpenSSL 设置成为一个过滤器,比如用于 UU 或 Base64 编码的过滤器。

在这里对 BIO 库进行全面说明有点麻烦,所以我将根据需要一点一点地介绍它。首先,我将向您展示如何建立一个标准的套接字连接。相对于使用 BSD 套接字库,该操作需要的代码行更少一些。

在建立连接(无论安全与否)之前,要创建一个指向 BIO 对象的指针。这类似于在标准 C 中为文件流创建 FILE 指针。


清单 2. 指针
BIO * bio;  

打开连接

创建新的连接需要调用 BIO_new_connect 。您可以在同一个调用中同时指定主机名和端口号。也可以将其拆分为两个单独的调用:一个是创建连接并设置主机名的 BIO_new_connect 调用,另一个是设置端口号的 BIO_set_conn_port (或者 BIO_set_conn_int_port )调用。

不管怎样,一旦 BIO 的主机名和端口号都已指定,该指针会尝试打开连接。没有什么可以影响它。如果创建 BIO 对象时遇到问题,指针将会是 NULL。为了确保连接成功,必须执行 BIO_do_connect 调用。


清单 3. 创建并打开连接
bio = BIO_new_connect("hostname:port");  if(bio == NULL)  {      /* Handle the failure */  }  if(BIO_do_connect(bio) <= 0)  {      /* Handle failed connection */  }  

在这里,第一行代码使用指定的主机名和端口创建了一个新的 BIO 对象,并以所示风格对该对象进行 格式化。例如,如果您要连接到 www.ibm.com 的 80 端口,那么该字符串将是 www.ibm.com:80 。调用 BIO_do_connect 检查连接是否成功。如果出错,则返回 0 或 -1。

与服务器进行通信

不管 BIO 对象是套接字还是文件,对其进行的读和写操作都是通过以下两个函数来完成的: BIO_readBIO_write 。很简单,对吧?精彩之处就在于它始终如此。

BIO_read 将尝试从服务器读取一定数目的字节。它返回读取的字节数、 0 或者 -1。在受阻塞的连接中,该函数返回 0,表示连接已经关闭,而 -1 则表示连接出现错误。在非阻塞连接的情况下,返回 0 表示没有可以获得的数据,返回 -1 表示连接出错。可以调用 BIO_should_retry 来确定是否可能重复出现该错误。


清单 4. 从连接读取
int x = BIO_read(bio, buf, len);  if(x == 0)  {      /* Handle closed connection */  }  else if(x < 0)  {     if(! BIO_should_retry(bio))      {          /* Handle failed read here */      }      /* Do something to handle the retry */  }  

BIO_write 会试着将字节写入套接字。它将返回实际写入的字节数、0 或者 -1。同 BIO_read ,0 或 -1 不一定表示错误。 BIO_should_retry 是找出问题的途径。如果需要重试写操作,它必须使用和前一次完全相同的参数。


清单 5. 写入到连接
if(BIO_write(bio, buf, len) <= 0)  {      if(! BIO_should_retry(bio))      {          /* Handle failed write here */      }      /* Do something to handle the retry */  }  

关闭连接

关闭连接也很简单。您可以使用以下两种方式之一来关闭连接: BIO_resetBIO_free_all 。如果您还需要重新使用对象,那么请使用第一种方式。如果您不再重新使用它,则可以使用第二种方式。

BIO_reset 关闭连接并重新设置 BIO 对象的内部状态,以便可以重新使用连接。如果要在整个应用程序中使用同一对象,比如使用一台安全的聊天客户机,那么这样做是有益的。该函数没有返回值。

BIO_free_all 所做正如其所言:它释放内部结构体,并释放所有相关联的内存,其中包括关闭相关联的套接字。如果将 BIO 嵌入于一个类中,那么应该在类的析构函数中使用这个调用。


清单 6. 关闭连接
/* To reuse the connection, use this line */  BIO_reset(bio);  /* To free it from memory, use this line */  BIO_free_all(bio);  





回页首


建立安全连接

现在需要给出建立安全连接需要做哪些事情。惟一要改变的地方就是建立并进行连接。其他所有内容都是相同的。

安全连接要求在连接建立后进行握手。在握手过程中,服务器向客户机发送一个证书,然后,客户机根据一组可信任证书来核实该证书。它还将检查证书,以确保它没有过期。要检验证书是可信任的,需要在连接建立之前提前加载一个可信任证书库。

只有在服务器发出请求时,客户机才会向服务器发送一个证书。该过程叫做客户机认证。使用证书,在客户机和服务器之间传递密码参数,以建立安全连接。尽管握手是在建立连接之后才进行的,但是客户机或服务器可以在任何时刻请求进行一次新的握手。

参考资料 部分中列出的 Netscasp 文章和 RFC 2246 ,对握手以及建立安全连接的其他方面的知识进行了更详尽的论述。

为安全连接进行设置

为安全连接进行设置要多几行代码。同时需要有另一个类型为 SSL_CTX 的指针。该结构保存了一些 SSL 信息。您也可以利用它通过 BIO 库建立 SSL 连接。可以通过使用 SSL 方法函数调用 SSL_CTX_new 来创建这个结构,该方法函数通常是 SSLv23_client_method

还需要另一个 SSL 类型的指针来保持 SSL 连接结构(这是短时间就能完成的一些连接所必需的)。以后还可以用该 SSL 指针来检查连接信息或设置其他 SSL 参数。


清单 7. 设置 SSL 指针
SSL_CTX * ctx = SSL_CTX_new(SSLv23_client_method());  SSL * ssl;  

加载可信任证书库

在创建上下文结构之后,必须加载一个可信任证书库。这是成功验证每个证书所必需的。如果不能确认证书是可信任的,那么 OpenSSL 会将证书标记为无效(但连接仍可以继续)。

OpenSSL 附带了一组可信任证书。它们位于源文件树的 certs 目录中。不过,每个证书都是一个独立的文件 �� 也就是说,需要单独加载每一个证书。在 certs 目录下,还有一个存放过期证书的子目录。试图加载这些证书将会出错。

如果您愿意,可以分别加载每一个文件,但为了简便起见,最新的 OpenSSL 发行版本的可信任证书通常存放在源代码档案文件中,这些档案文件位于名为"TrustStore.pem"的单个文件中。如果已经有了一个可信任证书库,并打算将它用于特定的项目中,那么只需使用您的文件替换清单 8 中的"TrustStore.pem"(或者使用单独的函数调用将它们全部加载)即可。

可以调用 SSL_CTX_load_verify_locations 来加载可信任证书库文件。这里要用到三个参数:上下文指针、可信任库文件的路径和文件名,以及证书所在目录的路径。必须指定可信任库文件或证书的目录。如果指定成功,则返回 1,如果遇到问题,则返回 0。


清单 8. 加载信任库
if(! SSL_CTX_load_verify_locations(ctx, "/path/to/TrustStore.pem", NULL))  {      /* Handle failed load here */  }  

如果打算使用目录存储可信任库,那么必须要以特定的方式命名文件。OpenSSL 文档清楚地说明了应该如何去做,不过,OpenSSL 附带了一个名为 c_rehash 的工具,它可以将文件夹配置为可用于 SSL_CTX_load_verify_locations 的路径参数。


清单 9. 配置证书文件夹并使用它
/* Use this at the command line */  c_rehash /path/to/certfolder  /* then call this from within the application */  if(! SSL_CTX_load_verify_locations(ctx, NULL, "/path/to/certfolder"))  {      /* Handle error here */  }  

为了指定所有需要的验证证书,您可以根据需要命名任意数量的单独文件或文件夹。您还可以同时指定文件和文件夹。

创建连接

将指向 SSL 上下文的指针作为惟一参数,使用 BIO_new_ssl_connect 创建 BIO 对象。还需要获得指向 SSL 结构的指针。在本文中,只将该指针用于 SSL_set_mode 函数。而这个函数是用来设置 SSL_MODE_AUTO_RETRY 标记的。使用这个选项进行设置,如果服务器突然希望进行一次新的握手,那么 OpenSSL 可以在后台处理它。如果没有这个选项,当服务器希望进行一次新的握手时,进行读或写操作都将返回一个错误,同时还会在该过程中设置 retry 标记。


清单 10. 设置 BIO 对象
bio = BIO_new_ssl_connect(ctx);  BIO_get_ssl(bio, & ssl);  SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);  

设置 SSL 上下文结构之后,就可以创建连接了。主机名是使用 BIO_set_conn_hostname 函数设置的。主机名和端口的指定格式与前面的相同。该函数还可以打开到主机的连接。为了确认已经成功打开连接,必须执行对 BIO_do_connect 的调用。该调用还将执行握手来建立安全连接。


清单 11. 打开安全连接
/* Attempt to connect */  BIO_set_conn_hostname(bio, "hostname:port");  /* Verify the connection opened and perform the handshake */  if(BIO_do_connect(bio) <= 0)  {      /* Handle failed connection */  }  

连接建立后,必须检查证书,以确定它是否有效。实际上,OpenSSL 为我们完成了这项任务。如果证书有致命的问题(例如,哈希值无效),那么将无法建立连接。但是,如果证书的问题并不是致命的(当它已经过期或者尚不合法时),那么仍可以继续使用连接。

可以将 SSL 结构作为惟一参数,调用 SSL_get_verify_result 来查明证书是否通过了 OpenSSL 的检验。如果证书通过了包括信任检查在内的 OpenSSL 的内部检查,则返回 X509_V_OK。如果有地方出了问题,则返回一个错误代码,该代码被记录在命令行工具的 verify 选项下。

应该注意的是,验证失败并不意味着连接不能使用。是否应该使用连接取决于验证结果和安全方面的考虑。例如,失败的信任验证可能只是意味着没有可信任的证书。连接仍然可用,只是需要从思想上提高安全意识。


清单 12. 检查证书是否有效
if(SSL_get_verify_result(ssl) != X509_V_OK)  {      /* Handle the failed verification */  }  

这就是所需要的全部操作。通常,与服务器进行通信都要使用 BIO_readBIO_write 。并且只需调用 BIO_free_allBIO_reset ,就可以关闭连接,具体调用哪一个方法取决于是否重用 BIO。

必须在结束应用程序之前的某个时刻释放 SSL 上下文结构。可以调用 SSL_CTX_free 来释放该结构。


清单 13. 清除 SSL 上下文
SSL_CTX_free(ctx);  





回页首


错误检测

显然 OpenSSL 抛出了某种类型的错误。这意味着什么?首先,您需要得到错误代码本身; ERR_get_error 可以完成这项任务;然后,需要将错误代码转换为错误字符串,它是一个指向由 SSL_load_error_stringsERR_load_BIO_strings 加载到内存中的永久字符串的指针。可以在一个嵌套调用中完成这项操作。

表 1 略述了从错误栈检索错误的方法。清单 24 展示了如何打印文本字符串中的最后一个错误信息。

表 1. 从栈中检索错误

ERR_reason_error_string 返回一个静态字符串的指针,然后可以将字符串显示在屏幕上、写入文件,或者以任何您希望的方式进行处理
ERR_lib_error_string 指出错误发生在哪个库中
ERR_func_error_string 返回导致错误的 OpenSSL 函数


清单 14. 打印出最后一个错误
printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()));  

您还可以让库给出预先格式化了的错误字符串。可以调用 ERR_error_string 来得到该字符串。该函数将错误代码和一个预分配的缓冲区作为参数。而这个缓冲区必须是 256 字节长。如果参数为 NULL,则 OpenSSL 会将字符串写入到一个长度为 256 字节的静态缓冲区中,并返回指向该缓冲区的指针。否则,它将返回您给出的指针。如果您选择的是静态缓冲区选项,那么在下一次调用 ERR_error_string 时,该缓冲区会被覆盖。


清单 15. 获得预先格式化的错误字符串
printf("%s\n", ERR_error_string(ERR_get_error(), NULL));  

您还可以将整个错误队列转储到文件或 BIO 中。可以通过 ERR_print_errorsERR_print_errors_fp 来实现这项操作。队列是以可读格式被转储的。第一个函数将队列发送到 BIO ,第二个函数将队列发送到 FILE 。字符串格式如下(引自 OpenSSL 文档):

[pid]:error:[error code]:[library name]:[function name]:[reason string]:[file name]:[line]:[optional text message]

其中, [pid] 是进程 ID, [error code] 是一个 8 位十六进制代码, [file name] 是 OpenSSL 库中的源代码文件, [line] 是源文件中的行号。


清单 16. 转储错误队列
ERR_print_errors_fp(FILE *);  ERR_print_errors(BIO *);  





回页首


开始做吧

使用 OpenSSL 创建基本的连接并不困难,但是,当试着确定该如何去做时,文档可能是一个小障碍。本文向您介绍了一些基本概念,但 OpenSSL 还有很多灵活之处有待发掘,而且您还可能需要一些高级设置,以便项目能够充分利用 SSL 的功能。

本文中有两个样例。一个样例展示了到 http://www.verisign.com/ 的非安全连接,另一个则展示了到 http://www.verisign.com/ 的安全 SSL 连接。两者都是连接到服务器并下载其主页。它们没有进行任何安全检查,而且库中的所有设置都是默认值 �� 作为本文的一部分,应该只将这些用于教学目的。

在任何支持的平台上,源代码的编译都应该是非常容易的,不过我建议您使用最新版本的 OpenSSL。在撰写本文时,OpenSSL 的最新版本是 0.9.7d。


2007年11月2日星期五

股市看盘秘诀十八条

股市看盘秘诀十八条
       1, 对大盘,大盘股(白线)上得比小盘股(黄线)快,要出现回调,而黄线上涨比白线快,则会带动白线上.

  2,涨跌比率大于1而大盘跌,表明空方势强,反之多方强.此状况高位看跌低位看涨.

  3,成交量大的股票开始走软,或者前期股市的热门板块走软,当小心行情已接近尾声.

  4,股票基本走软,市场在热点消失还没有出现新市场热点的时候,不要轻易去买股票.

  5, 成交量屡创天量,而股价涨幅不大,应随时考虑派发,反之成交量极度萎缩不要轻易抛出股票.

  6,大盘5分种成交明细若出现价量配合理想当看好后市,反之要小心.

  7,成交量若上午太小,则下午反弹的机会多,如上午太大,则下午下跌概率大.

  8,操作时间最好在下午,因为下午操作有上午的盘子作依托,运用60分种K线分析,可靠性好.

  9,上涨的股票若压盘出奇的大,但最终被消灭,表明仍会上涨.

  10,一般股票的升跌贴着均价运行,若发生背离将会出现反转.

  11,盘面经常出现大手笔买卖,买进时一下吃高几个档位,表明大户在进货.

  12, 个股在盘整或下跌时,内盘大于外盘,且阴线实体小,成交量大,日后该股有行情的可能性大;大盘暴跌,而该股没跌多少或者根本没跌,下档接盘强,成交放得很大,后市有戏的可能大.

  13,股价上冲的线头(曲线)绝对的多于下跌的线头时当看好该股.

  14,在下跌的势道里,应选逆势股;在上涨的势道里,应选大手笔买卖的股票.

  15, 开盘数分种就把股价往上直拉,而均线没有跟上,往往都是以当天失败的形式而告终.

  16, 当日下跌放巨量,但收的阴线实体不大,而且大部分时间在昨日收盘以上运行,第二天涨的机会多.

  17, 涨幅在5-7%以上,内盘大于外盘,高点不断创新,低点不断抬高,说明有机构大户在进货.

  18,分价表若是均匀分布说明大户不在里面,否则有大户介入.

--
一步一步教你从互联网赚钱 http://www.zqzn.com/index.asp?rid=key480769
投资理财 http://li-cai.blogspot.com/