Oracle OS 认证, 口令文件

 1、os认证
    oracle安装之后默认情况下是启用了os认证的,这里提到的os认证是指服务器端os认证。os认证的意思把登录数据库的用户和口令校验放在了操作系统一级。如果以安装oracle时的用户登录os,那么此时在登录oracle数据库时不需要任何验证,如:

    SQL> connect /as sysdba
    已连接。

    SQL> connect sys/aaa@dmt as sysdba
    已连接。

    SQL> connect sys/bbb as sysdba
    已连接。

    SQL> connect aaa/bbb as sysdba
    已连接。

    SQL> show user
    USER 为 "SYS"

    SQL>

    不论输入什么用户(哪怕这个用户如aaa在数据库中根本不存在),只要以sysdba权限连接数据库,都可以连接上,并且连接用户是sys,这样很方便,有时候,如果忘记了数据库的密码,而又想登录数据库,可以通过这种方式,前提是在数据库服务器上;但是方便的同时也带来了一些安全隐患,于是很多人想屏蔽os认证,在win下只要把oracle_home/NETWORK/admin/sqlnet.ora中的SQLNET.AUTHENTICATION_SERVICES= (nts)nts改成none或者注释掉这句话(在前面加上#),就可以屏蔽os功能,要想以sys用户连上数据库必须输入正确的sys口令,如:

    SQL> connect /as sysdba
    ERROR:
    ORA-01031: 权限不足

    SQL> connect sys/aaa as sysdba
    ERROR:
    ORA-01017: 用户名/口令无效; 登录被拒绝

    SQL> connect aaa/bbb as sysdba
    ERROR:
    ORA-01031: 权限不足

    SQL> connect sys/system as sysdba
    已连接。

    SQL>

    或者可以把oracle的安装用户从组ora_dba中删除掉,当然也可以直接把ora_dba这个组也删除,都可以屏蔽os功能。在unix/linux下也可以在文件sqlnet.ora中增加SQLNET.AUTHENTICATION_SERVICES=(none)以及删除dba(groupdel dba)组或者把oracle用户从dba组中删除都可以屏蔽os认证。利用这两种方法屏蔽os功能似乎总有些让人不放心,或者说不能让人完全信服,因为毕竟系统管理员还是可以创建ora_dba or dba组以及修改sqlnet.ora文件,如何彻底屏蔽os功能?让它"永世不得翻身"呢?我没有这方面的经验,大家可以补充!

    2、口令文件
    oracle的口令文件的作用是存放所有以sysdba或者sysoper权限连接数据库的用户的口令,如果想以sysdba权限远程连接数据库,必须使用口令文件,否则不能连上,由于sys用户在连接数据库时必须以sysdba or sysoper方式,也就是说sys用户要想连接数据库必须使用口令文件,因此我认为在数据库中存放sys用户的口令其实没有任何意义!使用口令文件的好处是即使数据库不处于open状态,依然可以通过口令文件验证来连接数据库。开始安装完oracle,没有给普通用户授予sysdba权限,口令文件中只存放了sys的口令,如果之后把sysdba权限授予了普通用户,那么此时会把普通用户的口令从数据库中读到口令文件中保存下来,当然这时必须要求数据库处于open状态。如:

    SQL> grant sysdba to test;
    授权成功。

    SQL> connect test/aaa@orcl as sysdba
    ERROR:
    ORA-01017: 用户名/口令无效; 登录被拒绝
    警告: 您不再连接到 ORACLE。

    SQL> connect test/test@orcl as sysdba
    已连接。

    SQL> alter database close;
    数据库已更改。

    SQL> grant sysdba, sysoper to test;
    grant sysdba, sysoper to test
    *
    第 1 行出现错误:
    ORA-01109: 数据库未打开

    到底有几个用户被授予了sysdba或者sysoper权限,可以通过查询如下v$pwfile_users获得,v$pwfile_users的信息就是源于口令文件的(This view lists users who have been granted SYSDBA and SYSOPER privileges as derived from the password file.)

    SQL> select * from v$pwfile_users;
    USERNAME SYSDB SYSOP
    ------------------------------ ----- -----
    SYS TRUE TRUE
    TEST TRUE FALSE

    到底可以有几个用户被授予sysdba或者sysoper权限,是由创建口令文件时指定的entries数决定的,准确的说还不完全是,最终还和os block的大小有关,如果entries指定了5,一个os block可以存放8个用户的口令,那么可以由8个用户被授予sysdba或者sysoper。

    下面看一个简单的测试:
    SQL> declare
      2     v_string varchar2(100);
      3  begin
      4  for i in 1..100 loop
      5     v_string := 'create user test'||i||' identified by test'||i;
      6     execute immediate v_string ;
      7  end loop;
      8  end;
      9  /
    PL/SQL 过程已成功完成。

    SQL> select count(*) from dba_users where username like '%TEST%';
      COUNT(*)
    ----------
           101

    这里之所以是101,是因为之前已经创建过test用户

    SQL> declare
      2     v_string varchar2(100);
      3  begin
      4          for i in 1..100 loop
      5             v_string := 'grant sysdba to test'||i;
      6                  execute immediate v_string ;
      7          end loop ;
      8  end ;
      9  /

    declare
    *
    第 1 行出现错误:
    ORA-01996: GRANT 失败: 口令文件 '' 已满
    ORA-06512: 在 line 6

    SQL> select * from v$pwfile_users;
    USERNAME                       SYSDB SYSOP
    ------------------------------ ----- -----
    SYS                            TRUE  TRUE
    TEST1                          TRUE  FALSE
    TEST2                          TRUE  FALSE
    TEST3                          TRUE  FALSE
    TEST4                          TRUE  FALSE
    TEST5                          TRUE  FALSE
    TEST6                          TRUE  FALSE
    TEST7                          TRUE  FALSE
    TEST8                          TRUE  FALSE

    已选择9行。

    SQL>

    可以清楚的看到v$pwfile_users里面并不是创建口令文件时指定的entries=5而是9条记录,意味着9个用户的口令占用了一个os block,其实也可能是多个os block,总之这些block都是满的,但是观察口令文件,还是占了2k,这是我解释不清的地方。通过os命令发现;每个簇字节数4096;这里其实就是os block 大小实际上是4k,但是口令文件占用了2k,根本没有用满一个os block,不知道何故,也是我的疑惑 (
    This parameter specifies the number of entries that you require the password file to accept. This number corresponds to the number of distinct users allowed to connect to the database as SYSDBA or SYSOPER. The actual number of allowable entries can be higher than the number of users, because the ORAPWD utility continues to assign password entries until an operating system block is filled. For example, if your operating system block size is 512 bytes, it holds four password entries. The number of password entries allocated is always a multiple of four.
    )

    win下查看os block大小
    C:\WINDOWS\system32>fsutil fsinfo ntfsinfo e:
    NTFS 卷序列号 :       0x12afb454f6e54b31
    版本 :                         3.1
    区数量 :                  0x00000000040270d0
    簇总数 :                  0x0000000000804e1a
    可用簇  :                  0x00000000000b8d41
    保留总数 :                  0x0000000000000000
    每个扇区字节数  :               512
    每个簇字节数 :               4096
    每个 FileRecord 段的字节数    : 1024
    每个 FileRecord 段的簇数 : 0
    Mft 有效数据长度 :           0x00000000058d0000
    Mft 起始 Lcn  :                  0x0000000000000004
    Mft2 起始 Lcn :                  0x0000000000080000
    Mft 区域起始 :                  0x0000000000483740
    Mft 区域结尾   :                  0x000000000049c760

    C:WINDOWS\system32>
    还有一个问题修改了口令,口令长度增加了,按说占用的空间多了,但是查询v$pwfile_users发现还是9条记录?不过这个问题突然想到了答案,那就是不论我们的口令多长,加密之后的长度几乎都是相同的,也就是说口令文件占用的大小和口令指定的长度几乎关系不大!

    SQL> edit
    已写入 file afiedt.buf
      1  declare
      2     v_string varchar2(100);
      3  begin
      4          for i in 1..100 loop
      5             v_string := 'alter user test'||i||' identified by  aaaaaaaaaaaaaaaaaaaaaa'||i;
      6                  execute immediate v_string ;
      7          end loop ;
      8* end ;
    SQL> /
    PL/SQL 过程已成功完成。

    SQL> declare
      2     v_string varchar2(100);
      3  begin
      4          for i in 1..100 loop
      5             v_string := 'grant sysdba to test'||i;
      6                  execute immediate v_string ;
      7          end loop ;
      8  end ;
      9  /
    declare
    *
    第 1 行出现错误:
    ORA-01996: GRANT 失败: 口令文件 '' 已满
    ORA-06512: 在 line 6

    SQL> select * from v$pwfile_users;
    USERNAME                       SYSDB SYSOP
    ------------------------------ ----- -----
    SYS                            TRUE  TRUE
    TEST1                          TRUE  FALSE
    TEST2                          TRUE  FALSE
    TEST3                          TRUE  FALSE
    TEST4                          TRUE  FALSE
    TEST5                          TRUE  FALSE
    TEST6                          TRUE  FALSE
    TEST7                          TRUE  FALSE
    TEST8                          TRUE  FALSE

    已选择9行。

    SQL>
    E:\oracle\product\10.2.0\db_1\data\base>orapwd file=E:\oracle\product\10.2.0\db_1
    databasepwd.ora password=system entries=5
    OPW-00005: 存在相同名称的文件 - 请删除或重命名

    E:\oracle\product\10.2.0\db_1\data\base>orapwd file=E:oracleproduct10.2.0db_1
    databasepwd.ora password=system entries=5 force=y

    创建口令文件需要注意的是=前后没有空格!另外值得一提的是10g增加了一个新的参数force default值n,它的作用类似于创建表空间时的reuse功能,当同名文件存在时是否覆盖。

    是否使用口令文件,是通过oracle提供的一个参数remote_login_passwordfile来控制的,remote_login_passwordfile有none,shared,exclusive3个值,none表示不使用口令文件,exclusive表示实例独占使用口令文件,也就是各自实例使用单独的口令文件,shared表示多个实例共享一个口令文件,缺省情况下,win下口令文件的格式是pwdsid.ora,unix下的格式是orapwSID(大小写敏感),unix下寻找口令文件的顺序是oracle_home\dbs\orapwSID,如果找不到,会在dbs目录想寻找orapw文件,如果找不到9i下会报错,数据库可以启动到mount状态,当然再次alter database open之后还是可以打开数据库。10g下open数据库时不在检查口令文件。win下如果在oracle_home/database/下找不到pwdsid.ora文件,不会寻找任何文件。这里所说的win下如果找不到PWDsid.ora文件之后不会寻找任何文件其实是相对unix下如果找不到orapwSID文件之后会寻找orapw文件而言的。其实win下寻找口令文件也是有顺序的。寻找顺序是这样的:首先寻找注册表中ora_sid_pwfile环境变量所指向的口令文件,其次寻找ora_pwfile执行的口令文件,最后才寻找$ORACLE_HOME/database/PWDsid.ora,下面做一个简单的测试:

    开始存在一个口令文件PWDtsid.ora,之后又创建了两个口令文件pwd.ora和orapwd.ora
    C:>orapwd file=E:\oracle\product\10.2.0\db_1\databasepwd.ora password=manager entries=5 force=y

    C:>orapwd file=E:\oracle\product\10.2.0\db_1\databaseorapwd.ora password=manager_system entries=5

    C:>e:
    E:>cd E:\oracle\product\10.2.0\db_1\database

    E:\oracle\product\10.2.0\db_1\database>dir *pwd*

     驱动器 E 中的卷没有标签。
     卷的序列号是 F6E5-4B31
     E:\oracle\product\10.2.0\db_1\database 的目录

    2007-12-07  21:30             2,048 orapwd.ora
    2007-12-07  21:29             2,048 pwd.ora
    2007-12-06  21:44             2,048 PWDtsid.ora

    3个口令文件的口令分别是system, manager, system_manager没有什么特别的意义,都是随意指定的,其中在注册表中ora_tsid_pwfile指向了文件E:\oracle\product\10.2.0\db_1\databasepwd.ora,ora_pwfile指向了E:\oracle\product\10.2.0\db_1\databaseorapwd.ora,然后通过远程client端进行测试:

    SQL> connect sys/system@testdb as sysdba
    ERROR:
    ORA-01017: 用户名/口令无效; 登录被拒绝
    警告: 您不再连接到 ORACLE。

    SQL> connect sys/manager@testdb as sysdba
    已连接。

    SQL> connect sys/manager_system@testdb as sysdba
    ERROR:
    ORA-01017: 用户名/口令无效; 登录被拒绝
    警告: 您不再连接到 ORACLE。

    SQL>

    测试结果显示要求输入的口令是manager,而manager对应的口令文件是环境变量ora_tsid_pwfile所指向的pwd.ora,之后删除环境变量ora_tsid_pwfile再次连接:


    SQL> connect sys/system@testdb as sysdba
    ERROR:
    ORA-01017: 用户名/口令无效; 登录被拒绝
    警告: 您不再连接到 ORACLE。

    SQL> connect sys/manager_system@testdb as sysdba
    已连接。

    SQL>
    这次要求输入的口令是manager_system,而manager_system对应的口令文件是环境变量ora_pwfile所指向的orapwd.ora,之后删除环境变量ora_pwfile进行连接测试:

    SQL> connect sys/system@testdb as sysdba
    已连接。

    SQL>

    连接成功,system对应的口令文件正是$ORACLE_HOME/database/PWDtsid.ora

    接着上面介绍共享口令文件,由于在unix下会寻找orapw文件(该文件不含sid的信息),因此各个实例可以shared口令文件,前提是需要把参数remote_login_passwordfile设置为shared,该参数是静态参数,修改之后需要重启实例,当然也可以通过连接的方式(unix下ls)实现口令文件共享,不过没感觉到共享口令文件有什么好处;win下可以通过在注册表中指定环境变量ora_sid_pwfile或者ora_pwfile来改变口令文件的位置和名称,从而也可以实现口令文件共享。

    共享口令文件会有很多问题:
    首先要求所有的sys口令相同,其次orcl库上的用户xys被授予了sysdba,结果在test1库上通过v$pwfile_users也可以看到xys用户。

    SQL> connect sys/system as sysdba
    ERROR:
    ORA-01017: invalid username/password; logon denied

    SQL> connect sys/manager as sysdba
    已连接到空闲例程。

    SQL> startup
    ORACLE 例程已经启动。
    Total System Global Area 167772160 bytes
    Fixed Size 1247900 bytes
    Variable Size 62915940 bytes
    Database Buffers 100663296 bytes
    Redo Buffers 2945024 bytes
    数据库装载完毕。
    数据库已经打开。

    SQL> alter user sys identified by system;
    用户已更改。

    SQL> show user
    USER 为 SYS;

    SQL> show parameter db_name
    NAME TYPE VALUE
    ------------------------------------ ----------- ------------------------------
    db_name string test1

    SQL> select * from v$pwfile_users;
    USERNAME SYSDB SYSOP
    ------------------------------ ----- -----
    SYS TRUE TRUE
    XYS TRUE FALSE

    SQL> select username from dba_users;
    USERNAME
    ------------------------------
    OUTLN
    SYS
    SYSTEM
    TEST
    DBSNMP
    TSMSYS
    DIP
    已选择7行。

    从上面查询结果看到数据库orcl和test1,准确的说是实例共享了口令文件之后,test1中根本不存在用户xys,但是通过v$pwfile_users还是查询出来了

    还有一个问题是如果remote_login_passwordfile=shared则sys的口令通过

    alter user...不能修改!

    SQL> show parameter remote_log
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    remote_login_passwordfile            string      SHARED

    SQL> alter user sys identified by manager;
    alter user sys identified by manager
    *
    第 1 行出现错误:
    ORA-28046: 不允许更改 SYS 口令

    提到alter user...这个系统权限,我觉得oracle做的不是很安全,只要有了alter user权限,sys用户的口令可以随意修改

    ,另外凡是修改具有sysdba or sysoper权限的用户,如果通过alter user来修改口令,那么同时修改了口令文件和数据库中的口令。

    简单的测试如下:
    SQL> create user test11 identified by test11;
    用户已创建。

    SQL> grant connect , alter user to test11;
    授权成功。

    SQL> connect test11/test11
    已连接。

    SQL> CONNECT / as sysdba
    已连接。

    SQL> grant select on dba_users to test11;
    授权成功。

    SQL> connect test11/test11
    已连接。

    SQL> col username format a10
    SQL> col password format a30
    SQL> select password , username from dba_users where username ='SYS';
    PASSWORD                       USERNAME
    ------------------------------ ----------
    75800913E1B66343               SYS

    SQL> show user
    USER 为 TEST11;

    SQL> alter user sys identified by manager;
    用户已更改。

    SQL> select password , username from dba_users where username ='SYS';
    PASSWORD                       USERNAME
    ------------------------------ ----------
    5638228DAF52805F               SYS

    SQL>

    remote_login_passwordfile=shared时,也不能把sysdba or sysoper授予普通用户!

    SQL> grant sysdba to test;
    grant sysdba to test
    *
    第 1 行出现错误:
    ORA-01999: 口令文件不能在 SHARED 模式下更新

    SQL> grant sysoper to test;
    grant sysoper to test
    *
    第 1 行出现错误:
    ORA-01999: 口令文件不能在 SHARED 模式下更新

    通过上面两部分内容的解释,了解了os认证和口令文件之后,如果为了安全不想让用户以sysdba or sysoper权限连接数据库,可以通过上面的方法屏蔽os认证的同时静止使用口令文件。

    3、sysdba 和 sysoper
    很多人可能不了解sysdba and sysoper到底是什么,其实他们是oracle的system privilege,通过查询系统权限表system_privilege_map可以清楚的知道:

    SQL> select name from system_privilege_map where name like 'SYS%';
    NAME
    ----------------------------------------------------------------------------
    SYSOPER
    SYSDBA

    只不过这两个权限就是以这种方式发挥作用的!

    两种权限的比较在oracle doc上给出了明确的交代:
    The following operations are authorized by the SYSDBA and SYSOPER system privileges:
    System Privilege Operations Authorized
    SYSDBA Perform STARTUP and SHUTDOWN operations
    ALTER DATABASE: open, mount, back up, or change character set
    CREATE DATABASE
    DROP DATABASE
    CREATE SPFILE
    ALTER DATABASE ARCHIVELOG
    ALTER DATABASE RECOVER
    Includes the RESTRICTED SESSION privilege
    Effectively, this system privilege allows a user to connect as user SYS.
    SYSOPER Perform STARTUP and SHUTDOWN operations
    CREATE SPFILE
    ALTER DATABASE OPEN/MOUNT/BACKUP
    ALTER DATABASE ARCHIVELOG
    ALTER DATABASE RECOVER (Complete recovery only. Any form of incomplete recovery, such as UNTIL TIME|CHANGE|CANCEL|CONTROLFILE requires connecting as SYSDBA.)
    Includes the RESTRICTED SESSION privilege
    This privilege allows a user to perform basic operational tasks, but without the ability to look at user data.

    值的一提的是win下尤其是home版的xp控制面板中没有组的可操作界面,而oracle默认安装之后也没有为我们创建ora_oper 这个组,因此在以sysoper权限连接数据库时提示没有权限:

    SQL> connect / as sysoper
    ERROR:
    ORA-01031: 权限不足

    为了能够以sysoper方式连接数据库,于是可以通过dos命令方式创建ora_oper组,同时把os用户加入到这个组中:

    E:>net  localgroup ora_oper /add
    命令成功完成。

    E:>net  localgroup ora_oper wch /add
    命令成功完成。

    有关localgroup的详细说明可以通过命令net help localgroup获得更多的帮助,注意和group的区别,group用在domain中
    再次尝试接连,连接成功:
    SQL> connect / as sysoper
    已连接。

    SQL> show user
    USER 为 PUBLIC;

    SQL>
    但是需要注意的是以sysoper权限连接数据库时显示的schema是public,而以sysdba连接时显示的schema是我们众所周知的sys,这也是sysdba和sysoper的区别之一。

    同时需要注意的是在linux下默认是可以以sysoper 连接数据库的:

    [oracle@xys oracle]$ sqlplus /nolog
    SQL*Plus: Release 11.1.0.6.0 - Production on Fri Dec 7 23:52:49 2007
    Copyright (c) 1982, 2007, Oracle.  All rights reserved.
    SQL> connect / as sysoper
    Connected to an idle instance.

    SQL> create user wch identified externally;
    用户已创建。

    SQL> grant create session to wch;
    授权成功。

    SQL> show parameter auth
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- -------------------------
    os_authent_prefix                    string      OPS$
    remote_os_authent                    boolean     FALSE

    SQL> col username format a10
    SQL> col password format a30
    SQL> select username , password from dba_users where username='WCH';
    USERNAME   PASSWORD
    ---------- ------------------------------
    WCH        EXTERNAL

    SQL> connect /
    ERROR:
    ORA-01017: 用户名/口令无效; 登录被拒绝
    警告: 您不再连接到 ORACLE。

    SQL>

使用普通用户os认证的好处是可以在执行一些批处理脚本时屏蔽数据库连接用户的口令,如exp ,expdp . sqlldr等。