\documentstyle[times,fullpage,rcsid]{article} \rcs$Id$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Make _ actually generate an _, and allow line-breaking after it. \let\underscore=\_ \catcode`_=13 \def_{\underscore\penalty75\relax} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newcommand{\test}[1]{\begin{description} \setlength{\itemsep}{0pt} #1 \end{description} } \newcommand{\numtest}[2]{\begin{description} \setlength{\itemsep}{0pt} \Number{#1} #2 \end{description} } \newcommand{\Number}[1]{\item[Number:] #1} \newcommand{\Reason}[1]{\item[Reason:] #1} \newcommand{\Expected}[1]{\item[Expected:] #1} \newcommand{\Conditions}[1]{\item[Conditions:] #1} \newcommand{\Priority}[1]{\item[Priority:] #1} \newcommand{\Status}[1]{\item[Status:] #1} \newcommand{\Vtwonote}[1]{\item[V2 note:] #1} \newcommand{\Version}[1]{\item[Version:] #1} \newcommand{\Call}[1]{} %\newcommand{\Call}[1]{\item[Call:] #1} %\newcommand{\Number}[1]{} %\newcommand{\Reason}[1]{} %\newcommand{\Expected}[1]{} %\newcommand{\Conditions}[1]{} %\newcommand{\Priority}[1]{} \title{KADM5 Admin API\\ Unit Test Description\footnote{\rcsId}} \author{Jonathan I. Kamens} \begin{document} \maketitle %\tableofcontents \section{Introduction} The following is a description of a black-box unit test of the KADM5 API. Each API function is listed, followed by the tests that shoud be performed on it. The tests described here are based on the ``Kerberos Administration System KADM5 API Functional Specifications'', revision 1.68. This document was originally written based on the OpenVision API functional specifications, version 1.41, dated August 18, 1994, and many indications of the original version remain. All tests which test for success should verify, using some means other than the return value of the function being tested, that the requested operation was successfully performed. For example: for init, test that other operations can be performed after init; for destroy, test that other operations can't be performed after destroy; for modify functions, verify that all modifications to the database which should have taken place did, and that the new, modified data is in effect; for get operations, verify that the data retrieved is the data that should actually be in the database. The tests would be better if they compared the actual contents of the database before and after each test, rather than relying on the KADM5 API to report the results of changes. Similarly, all tests which test for failure should verify that the no component of the requested operation took place. For example: if init fails, other operations should not work. If a modify fails, all data in the database should be the same as it was before the attempt to modify, and the old data should still be what is enforced. Furthermore, tests which test for failure should verify that the failure code returned is correct for the specific failure condition tested. Most of the tests listed below should be run twice -- once locally on the server after linking against the server API library, and once talking to the server via authenticated Sun RPC after linking against the client API library. Tests which should only be run locally or via RPC are labelled with a ``local'' or ``RPC''. Furthermore, in addition to the tests labelled below, a test should be implemented to verify that a client can't perform operations on the server through the client API library when it's linked against standard Sun RPC instead of OpenV*Secure's authenticated Sun RPC. This will require a client with a modified version of ovsec_kadm_init which doesn't call auth_gssapi_create. This client should call this modified ovsec_kadm_init and then call some other admin API function, specifying arguments to both functions that would work if the authenticated Sun RPC had been used, but shouldn't if authentication wasn't used. The test should verify that the API function call after the init doesn't succeed. There is also another test to see if all the API functions handle getting an invalid server handle correctly. This is not done as part of the tests that are run through the TCL program cause the TCL program has no way of invalidating a server handle. So there is a program that calls init and changes the handle magic number, and then attempts to call each API function with the corrupted server handle. A number of tests have been added or changed to correspond with KADM5 API version 2. Tests which are only performed against the newer version specify the version number in the test description. \section{ovsec_kadm_init} \numtest{1}{ \Reason{An empty string realm is rejected.} \Status{Implemented} \Vtwonote{The empty string is now passed as the realm field of the parameters structure.} } \numtest{2}{ \Reason{A realm containing invalid characters is rejected.} \Status{Implemented} \Vtwonote{The invalid character is now passed as the realm field of the parameters structure.} } \numtest{2.5}{ \Reason{A non-existent realm is rejected.} \Status{Implemented} \Vtwonote{The non-existent realm is now passed as the realm field of the parameters structure.} } \numtest{3}{ \Reason{A bad service name representing an existing principal (different from the client principal) is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{4}{ \Reason{A bad service name representing a non-existent principal is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{5}{ \Reason{A bad service name identical to the (existing) client name is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{6}{ \Reason{A null password causes password prompting.} \Status{Implemented} } \numtest{7}{ \Reason{An empty-string causes password prompting} \Status{Implemented} } \numtest{8}{ \Reason{An incorrect password which is the password of another user is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{9}{ \Reason{An incorrect password which isn't the password of any user is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{10}{ \Reason{A null client_name is rejected.} \Status{Implemented} } % Empty string client name is legal. %\numtest{11}{ %\Reason{An empty-string client_name is rejected.} %} \numtest{12}{ \Reason{A client_name referring to a non-existent principal in the default realm is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{13}{ \Reason{A client_name referring to a non-existent principal with the local realm specified explicitly is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{14}{ \Reason{A client_name referring to a non-existent principal in a nonexistent realm is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{15}{ \Reason{A client_name referring to an existing principal in a nonexistent realm is rejected.} \Conditions{RPC} \Status{Implemented} } \numtest{16}{ \Reason{Valid invocation.} \Status{Implemented} } \numtest{17}{ \Reason{Valid invocation (explicit client realm).} \Status{Implemented} } \numtest{18}{ \Reason{Valid invocation (CHANGEPW_SERVICE).} \Status{Implemented} } \numtest{19}{ \Reason{Valid invocation (explicit service realm).} \Status{Implemented} \Vtwonote{The explicit realm is now passed as the realm field of the configuration parameters.} } \numtest{20}{ \Reason{Valid invocation (database access allowed after init).} \Status{Implemented} } %\numtest{21}{ %\Reason{Init fails when called twice in a row.} %\Status{Implemented} %} \numtest{22}{ \Reason{A null password causes master-key prompting.} \Conditions{local} \Status{Implemented} \Vtwonote{Obsolete.} } \numtest{22.5}{ \Reason{A empty string password causes master-key prompting.} \Conditions{local} \Status{Implemented} \Vtwonote{Obsolete.} } %\numtest{23}{ %\Reason{A non-null password causes reading from the kstash.} %\Conditions{local} %\Status{Implemented} %} \numtest{24}{ \Reason{Null service name is ignored in local invocation.} \Conditions{local} \Status{Implemented} } \numtest{25}{ \Reason{Non-null service name is ignored in local invocation.} \Conditions{local} \Status{Implemented} } %\numtest{26}{ %\Reason{Can't do ``get'' operation before calling init.} %\Status{Implemented} %} %\numtest{27}{ %\Reason{Can't do ``add'' operation before calling init.} %\Status{Implemented} %} %\numtest{28}{ %\Reason{Can't do ``modify'' operation before calling init.} %\Status{Implemented} %} %\numtest{29}{ %\Reason{Can't do ``delete'' operation before calling init.} %\Status{Implemented} %} \numtest{30}{ \Reason{Can init after failed init attempt.} \Conditions{local} \Status{Implemented} } \numtest{31}{ \Priority{High} \Reason{Return BAD_STRUCT_VERSION when the mask bits are set to invalid values} \Status{Implemented} } \numtest{32}{ \Priority{High} \Reason{Return BAD_STRUCT_VERSION when the mask bits are not set} \Status{Implemented} } \numtest{33}{ \Priority{High} \Reason{Return OLD_STRUCT_VERSION when attempting to use an old/unsupported structure version} \Status{Implemented} } \numtest{34}{ \Priority{High} \Reason{Return NEW_STRUCT_VERSION when attempting to use a newer version of of the structure then what is supported} \Status{Implemented} } \numtest{35}{ \Priority{High} \Reason{Return BAD_API_VERSION when the mask bits are set to invalid values} \Status{Implemented} } \numtest{36}{ \Priority{High} \Reason{Return BAD_API_VERSION when the mask bits are not set} \Status{Implemented} } \numtest{37}{ \Priority{High} \Reason{Return OLD_LIB_API_VERSION when using an old/unsuppored api version number} \Conditions{RPC} \Status{Implemented} } \numtest{38}{ \Priority{High} \Reason{Return OLD_SERVER_API_VERSION attempting to use an old/unsupported api version number} \Conditions{local} \Status{Implemented} } \numtest{39}{ \Priority{High} \Reason{Return NEW_LIB_API_VERSION when using a newer api version number then supported} \Conditions{RPC} \Status{Implemented} } \numtest{40}{ \Priority{High} \Reason{Return NEW_SERVER_API_VERSION when using a newer api version number then supported} \Conditions{local} \Status{Implemented} } \numtest{41}{ \Priority{High} \Reason{Return BAD_XXX_VERSION when the API and the structure version numbers are reversed} \Status{Implemented} } \numtest{42}{ \Priority{High} \Reason{Succeeds when using valid api and struct version numbers and masks} \Status{Implemented} } \numtest{43}{ \Priority{Low} \Reason{Returns two different server handle when called twice with same info} } \numtest{44}{ \Priority{Low} \Reason{Returns two different server handles when called twice with different info} } \numtest{45}{ \Priority{Bug fix, secure-install/3390} \Reason{Returns SECURE_PRINC_MISSING when ADMIN_SERVICE does not exist.} \Status{Implemented} } \numtest{46}{ \Priority{Bug fix, secure-install/3390} \Reason{Returns SECURE_PRINC_MISSING when CHANGEPW_SERVICE does not exist.} \Status{Implemented} } \numtest{100}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the profile field of the configuration parameters, if set.} \Status{Implemented} } \numtest{101}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the kadmind_port field of the configuration parameters, if set.} \Conditions{RPC} \Status{Implemented} } \numtest{102}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the admin_server field of the configuration parameters, if set with only an admin server name.} \Conditions{RPC} \Status{Implemented} } \numtest{102.5}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the admin_server field of the configuratin parameters, if set with a host name and port number.} \Conditions{RPC} } \numtest{103}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the dbname field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{104}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the admin_dbname field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{105}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the admin_lockfile field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{106}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the mkey_from_kbd field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{107}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the stash_file field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{108}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the mkey_name field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{109}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the max_life field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{110}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the max_rlife field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{111}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the expiration field of the configuration parameters, if set.} \Status{Implemented} \Conditions{local} } \numtest{112}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the flags field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{113}{ \Version{KADM5_API_VERSION_2} \Reason{Obeys the keysalts and num_keysalts field of the configuration parameters, if set.} \Conditions{local} \Status{Implemented} } \numtest{114}{ \Version{KADM5_API_VERSION_2} \Reason{Returns KADM5_BAD_SERVER_PARAMS if any client-only parameters are specified to server-side init.} \Conditions{local} \Status{Implemented} } \numtest{115}{ \Version{KADM5_API_VERSION_2} \Reason{Returns KADM5_BAD_CLIENT_PARAMS if any client-only parameters are specified to server-side init.} \Conditions{RPC} \Status{Implemented} } \numtest{116}{ \Version{KADM5_API_VERSION_2} \Reason{Two calls to init with clients having different privileges succeedes, and both clients maintain their correct privileges.} \Priority{Bug fix} \Conditions{RPC} \Status{Implemented} } \numtest{117}{ \Version{KADM5_API_VERSION_2} \Reason{The max_life field defaults to value specified in the API Functional Specification when kdc.conf is unreadable.} \Priority{Bug fix, krb5-admin/18} \Conditions{local} \Status{Implemented} } \numtest{150}{ \Version{KADM5_API_VERSION_2} \Reason{init_with_creds works when given an open ccache with a valid credential for ADMIN_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{151}{ \Version{KADM5_API_VERSION_2} \Reason{init_with_creds works when given an open ccache with a valid credential for CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{152}{ \Version{KADM5_API_VERSION_2} \Reason{init_with_creds fails with KRB5_FCC_NOFILE (was KADM5_GSS_ERROR) when given an open ccache with no credentials.} \Conditions{RPC} \Status{Implemented} } \numtest{153}{ \Version{KADM5_API_VERSION_2} \Reason{init_with_creds fails with KRB5_CC_NOTFOUND (was KADM5_GSS_ERROR) when given an open ccache without credentials for ADMIN_SERVICE or CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{154}{ \Version{KADM5_API_VERSION_2} \Reason{If the KRB5_KDC_PROFILE environment variable is set to a filename that does not exist, init fails with ENOENT.} \Conditions{RPC} \Status{Implemented} } \section{ovsec_kadm_destroy} \numtest{1}{ \Reason{Valid invocation.} \Status{Implemented} } %\numtest{2}{ %\Reason{Valid invocation (``get'' not allowed after destroy).} %\Status{Implemented} %} %\numtest{3}{ %\Reason{Valid invocation (``add'' not allowed after destroy).} %\Status{Implemented} %} %\numtest{4}{ %\Reason{Valid invocation (``modify'' not allowed after destroy).} %\Status{Implemented} %} %\numtest{5}{ %\Reason{Valid invocation (``delete'' not allowed after destroy).} %\Status{Implemented} %} %\numtest{6}{ %\Reason{Fails if database not initialized.} %\Status{Implemented} %} %\numtest{7}{ %\Reason{Fails if invoked twice in a row.} %\Status{Implemented} %} \numtest{8}{ \Reason{Database can be reinitialized after destroy.} \Status{Implemented} } \numtest{9}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{10}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{client} } \section{ovsec_kadm_create_principal} %In the tests below, ``getu'' refers to a user who has only ``get'' access, %''addu'' refers to a user who has only ``add'' access, ``modifyu'' refers to %a user who has only ``modify'' access, and ``deleteu'' refers to a user %who has only ``delete'' access. ``amu'' refers to a user with ``add'' and %''modify'' access. ``new_princ'' refers to a principal entry structure %filled in as follows: % % krb5_parse_name("newuser", \&new_princ.principal); % krb5_timeofday(\&new_princ.princ_expire_time); % new_princ.princ_expire_time += 130; % krb5_timeofday(\&new_princ.last_pwd_change); % new_princ.last_pwd_change += 140; % krb5_timeofday(\&new_princ.pw_expiration); % new_princ.pw_expiration += 150; % new_princ.max_life = 160; % krb5_parse_name("usera", \&new_princ.mod_name); % krb5_timeofday(\&new_princ.mod_date); % new_princ.mod_date += 170; % new_princ.attributes = 0xabcdabcd; % new_princ.kvno = 180; % new_princ.mkvno = 190; % new_princ.policy = null; % new_princ.aux_attributes = 0xdeadbeef; % %The offsets of 130 through 190 above are used to ensure that the %fields are all known to be different from each other, so that %accidentally switched fields can be detected. Some of the fields in %this structure may be changed by the tests, but they should clean up %after themselves. %\numtest{1}{ %\Reason{Fails if database not initialized.} %\Status{Implemented} %} \numtest{2}{ \Reason{Fails on null princ argument.} \Status{Implemented} } \numtest{3}{ \Reason{Fails on null password argument.} \Status{Implemented} } \numtest{4}{ \Reason{Fails on empty-string password argument.} \Status{Implemented} } \numtest{5}{ \Reason{Fails when mask contains undefined bit.} \Status{Implemented} } \numtest{6}{ \Reason{Fails when mask contains LAST_PWD_CHANGE bit.} \Status{Implemented} } \numtest{7}{ \Reason{Fails when mask contains MOD_TIME bit.} \Status{Implemented} } \numtest{8}{ \Reason{Fails when mask contains MOD_NAME bit.} \Status{Implemented} } \numtest{9}{ \Reason{Fails when mask contains MKVNO bit.} \Status{Implemented} } \numtest{10}{ \Reason{Fails when mask contains AUX_ATTRIBUTES bit.} \Status{Implemented} } \numtest{11}{ \Reason{Fails when mask contains POLICY_CLR bit.} \Status{Implemented} } \numtest{12}{ \Reason{Fails for caller with no access bits.} \Status{Implemented} } \numtest{13}{ \Reason{Fails when caller has ``get'' access and not ``add''.} \Conditions{RPC} \Status{Implemented} } \numtest{14}{ \Reason{Fails when caller has ``modify'' access and not ``add''.} \Conditions{RPC} \Status{Implemented} } \numtest{15}{ \Reason{Fails when caller has ``delete'' access and not ``add''.} \Conditions{RPC} \Status{Implemented} } \numtest{16}{ \Reason{Fails when caller connected with CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{17}{ \Reason{Fails on attempt to create existing principal.} \Status{Implemented} } \numtest{18}{ \Reason{Fails when password is too short.} \Status{Implemented} } \numtest{19}{ \Reason{Fails when password has too few classes.} \Status{Implemented} } \numtest{20}{ \Reason{Fails when password is in dictionary.} \Status{Implemented} } \numtest{21}{ \Reason{Nonexistent policy is rejected.} \Status{Implemented} } \numtest{22}{ \Reason{Fails on invalid principal name.} \Status{Implemented} } \numtest{23}{ \Reason{Valid invocation.} \Status{Implemented} } \numtest{24}{ \Reason{Succeeds when caller has ``add'' access and another one.} \Status{Implemented} } %\numtest{25}{ %\Reason{Fails when password is too short, when override_qual is true.} %} %\numtest{26}{ %\Reason{Fails when password has too few classes, when % override_qual is true.} %} %\numtest{27}{ %\Reason{Fails when password is in dictionary, when override_qual is % true.} %} \numtest{28}{ \Reason{Succeeds when assigning policy.} \Status{Implemented} } \numtest{29}{ \Priority{High} \Reason{Allows 0 (never) for princ_expire_time.} \Status{Implemented} } \numtest{30}{ \Reason{Allows 0 (never) for pw_expiration when there's no policy.} \Status{Implemented} } \numtest{31}{ \Reason{Allows 0 (never) for pw_expiration when there's a policy with 0 for pw_max_life.} \Status{Implemented} } \numtest{32}{ \Reason{Accepts 0 (never) for pw_expiration when there's a policy with non-zero pw_max_life, and sets pw_expiration to zero.} \Status{Implemented} } \numtest{33}{ \Reason{Accepts and sets non-zero pw_expiration when no policy.} \Status{Implemented} } \numtest{34}{ \Reason{Accepts and sets non-zero pw_expiration when there's a policy with zero pw_max_life.} \Status{Implemented} } \numtest{35}{ \Reason{Accepts and sets non-zero pw_expiration when there's a policy with pw_max_life later than the specified pw_expiration.} \Status{Implemented} } \numtest{36}{ \Reason{Accepts and sets non-zero pw_expiration greater than now_pw_max_life.} \Status{Implemented} } \numtest{37}{ \Priority{High} \Reason{Sets pw_expiration to 0 (never) if there's no policy and no specified pw_expiration.} \Status{Implemented} } \numtest{38}{ \Priority{High} \Reason{Sets pw_expiration to 0 (never) if it isn't specified and the policy has a 0 (never) pw_max_life.} \Status{Implemented} } \numtest{39}{ \Priority{High} \Reason{Sets pw_expiration to now + pw_max_life if it isn't specified and the policy has a non-zero pw_max_life.} \Status{Implemented} } \numtest{40}{ \Priority{High} \Reason{Allows 0 (forever) for max_life.} \Status{Implemented} } \numtest{41}{ \Priority{High} \Reason{Doesn't modify or free mod_name on success.} } \numtest{42}{ \Priority{High} \Reason{Doesn't modify or free mod_name on failure.} } \numtest{43}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{44}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \section{ovsec_kadm_delete_principal} %\numtest{1}{ %\Reason{Fails if database not initialized.} %\Status{Implemented} %} \numtest{2}{ \Reason{Fails on null principal.} \Status{Implemented} } % Empty string principal is legal. %\numtest{3}{ %\Reason{Fails on empty-string principal.} %} % There is not invalid principal names %\numtest{4}{ %\Reason{Fails on invalid principal name.} %} \numtest{5}{ \Priority{High} \Reason{Fails on nonexistent principal.} \Status{Implemented} } \numtest{6}{ \Priority{High} \Reason{Fails when caller connected with CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{7}{ \Priority{High} \Reason{Fails if caller has ``add'' access and not ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{8}{ \Priority{High} \Reason{Fails if caller has ``modify'' access and not ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{9}{ \Priority{High} \Reason{Fails if caller has ``get'' access and not ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{10}{ \Priority{High} \Reason{Fails if caller has no access bits.} \Conditions{RPC} \Status{Implemented} } \numtest{11}{ \Priority{High} \Reason{Valid invocation.} \Status{Implemented} } \numtest{12}{ \Priority{High} \Reason{Valid invocation (on principal with policy).} \Status{Implemented} } \numtest{13}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{14}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \section{ovsec_kadm_modify_principal} %\numtest{1}{ %\Reason{Fails if database not initialized.} %\Status{Implemented} %} \numtest{2}{ \Priority{High} \Reason{Fails if user connected with CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{3}{ \Reason{Fails on mask with undefined bit set.} \Status{Implemented} } \numtest{4}{ \Reason{Fails on mask with PRINCIPAL set.} \Status{Implemented} } \numtest{5}{ \Priority{High} \Reason{Fails on mask with LAST_PWD_CHANGE set.} \Status{Implemented} } \numtest{6}{ \Reason{Fails on mask with MOD_TIME set.} \Status{Implemented} } \numtest{7}{ \Reason{Fails on mask with MOD_NAME set.} \Status{Implemented} } \numtest{8}{ \Reason{Fails on mask with MKVNO set.} \Status{Implemented} } \numtest{9}{ \Priority{High} \Reason{Fails on mask with AUX_ATTRIBUTES set.} \Status{Implemented} } \numtest{10}{ \Reason{Fails on nonexistent principal.} \Status{Implemented} } \numtest{11}{ \Priority{High} \Reason{Fails for user with no access bits.} \Conditions{RPC} \Status{Implemented} } \numtest{12}{ \Priority{High} \Reason{Fails for user with ``get'' access.} \Conditions{RPC} \Status{Implemented} } \numtest{13}{ \Priority{High} \Reason{Fails for user with ``add'' access.} \Conditions{RPC} \Status{Implemented} } \numtest{14}{ \Priority{High} \Reason{Fails for user with ``delete'' access.} \Conditions{RPC} \Status{Implemented} } \numtest{15}{ \Priority{High} \Reason{Succeeds for user with ``modify'' access.} \Conditions{RPC} \Status{Implemented} } \numtest{16}{ \Reason{Succeeds for user with ``modify'' and another access.} \Conditions{RPC} \Status{Implemented} } \numtest{17}{ \Priority{High} \Reason{Fails when nonexistent policy is specified.} \Status{Implemented} } \numtest{18}{ \Priority{High} \Reason{Succeeds when existent policy is specified.} \Status{Implemented} } \numtest{19}{ \Reason{Updates policy count when setting policy from none.} \Status{Implemented} } \numtest{20}{ \Reason{Updates policy count when clearing policy from set.} \Status{Implemented} } \numtest{21}{ \Reason{Updates policy count when setting policy from other policy.} \Status{Implemented} } \numtest{21.5}{ \Reason{Policy reference count remains unchanged when policy is changed to itself.} \Status{Implemented.} } \numtest{22}{ \Reason{Allows 0 (never) for pw_expiration when there's no policy.} \Status{Implemented} } \numtest{23}{ \Reason{Allows 0 (never) for pw_expiration when there's a policy with 0 for pw_max_life.} \Status{Implemented} } \numtest{24}{ \Reason{Accepts 0 (never) for pw_expiration when there's a policy with non-zero pw_max_life, but actually sets pw_expiration to last_pwd_change + pw_max_life.} \Status{Implemented} } \numtest{25}{ \Reason{Accepts and sets non-zero pw_expiration when no policy.} \Status{Implemented} } \numtest{26}{ \Reason{Accepts and sets non-zero pw_expiration when there's a policy with zero pw_max_life.} \Status{Implemented} } \numtest{27}{ \Reason{Accepts and sets non-zero pw_expiration when there's a policy with pw_max_life later than the specified pw_expiration.} \Status{Implemented} } \numtest{28}{ \Reason{Accepts non-zero pw_expiration and limits it to last_pwd_change + pw_max_life when it's later than last_pwd_change + non-zero pw_max_life in policy.} \Status{Implemented} } \numtest{29}{ \Priority{High} \Reason{Sets pw_expiration to 0 (never) when a policy is cleared and no pw_expiration is specified.} \Status{Implemented} } \numtest{30}{ \Priority{High} \Reason{Sets pw_expiration to 0 (never) if it isn't specified and the new policy has a 0 (never) pw_max_life.} \Status{Implemented} } \numtest{31}{ \Priority{High} \Reason{Sets pw_expiration to now + pw_max_life if it isn't specified and the new policy has a non-zero pw_max_life.} \Status{Implemented} } \numtest{32}{ \Priority{High} \Reason{Accepts princ_expire_time change.} \Status{Implemented} } \numtest{33}{ \Priority{High} \Reason{Accepts attributes change.} \Status{Implemented} } \numtest{33.25}{ \Priority{High} \Reason{Accepts attributes change (KRB5_KDB_REQUIRES_PW_CHANGE).} \Status{Implemented} } \numtest{33.5}{ \Priority{High} \Reason{Accepts attributes change (KRB5_DISALLOW_TGT_BASE).} \Status{Implemented} } \numtest{33.75}{ \Priority{High} \Reason{Accepts attributes change (KRB5_PW_CHANGE_SERVICE).} \Status{Implemented} } \numtest{34}{ \Priority{High} \Reason{Accepts max_life change.} \Status{Implemented} } \numtest{35}{ \Priority{High} \Reason{Accepts kvno change.} \Status{Implemented} } \numtest{36}{ \Reason{Behaves correctly when policy is set to the same as it was before.} \Status{Implemented} } \numtest{37}{ \Reason{Behaves properly when POLICY_CLR is specified and there was no policy before.} \Status{Implemented} } \numtest{38}{ \Priority{High} \Reason{Accepts 0 (never) for princ_expire_time.} \Status{Implemented} } \numtest{39}{ \Priority{High} \Reason{Accepts 0 for max_life.} \Status{Implemented} } \numtest{40}{ \Reason{Rejects null principal argument.} \Status{Implemented} } \numtest{41}{ \Priority{High} \Reason{Doesn't modify or free mod_name on success.} } \numtest{42}{ \Priority{High} \Reason{Doesn't modify or free mod_name on failure.} } \numtest{43}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{44}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \numtest{100}{ \Version{KADM5_API_VERSION_2} \Priority{bug-fix} \Reason{Accepts max_rlife change.} \Status{Implemented} } \numtest{101}{ \Version{KADM5_API_VERSION_2} \Reason{Rejects last_success change.} \Status{Implemented} } \numtest{102}{ \Version{KADM5_API_VERSION_2} \Reason{Rejects last_failed change.} \Status{Implemented} } \numtest{103}{ \Version{KADM5_API_VERSION_2} \Reason{Rejects fail_auth_count change.} \Status{Implemented} } \numtest{103.5}{ \Version{KADM5_API_VERSION_2} \Reason{Rejects key_data change.} \Status{Implemented} } \numtest{104}{ \Version{KADM5_API_VERSION_2} \Reason{Accepts tl_data change when all types are greater than 256.} \Status{Implemented} } \numtest{105}{ \Version{KADM5_API_VERSION_2} \Reason{Returns KADM5_BAD_TL_TYPE when given tl_data with a type less than 256.} \Status{Implemented} } \section{ovsec_kadm_rename_principal} %\numtest{1}{ %\Reason{Fails if database not initialized.} %\Status{Implemented} %} \numtest{2}{ \Priority{High} \Reason{Fails if user connected with CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{3}{ \Priority{High} \Reason{Fails for user with no access bits.} \Conditions{RPC} \Status{Implemented} } \numtest{4}{ \Reason{Fails for user with ``modify'' access and not ``add'' or ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{5}{ \Reason{Fails for user with ``get'' access and not ``add'' or ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{6}{ \Reason{Fails for user with ``modify'' and ``add'' but not ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{7}{ \Reason{Fails for user with ``modify'' and ``delete'' but not ``add''.} \Conditions{RPC} \Status{Implemented} } \numtest{8}{ \Reason{Fails for user with ``get'' and ``add'' but not ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{9}{ \Reason{Fails for user with ``get'' and ``delete'' but not ``add.''} \Conditions{RPC} \Status{Implemented} } \numtest{10}{ \Reason{Fails for user with ``modify'', ``get'' and ``add'', but not ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{11}{ \Reason{Fails for user with ``modify'', ``get'' and ``delete'', but not ``add''.} \Conditions{RPC} \Status{Implemented} } \numtest{12}{ \Priority{High} \Reason{Fails for user with ``add'' but not ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{13}{ \Priority{High} \Reason{Fails for user with ``delete'' but not ``add''.} \Conditions{RPC} \Status{Implemented} } \numtest{14}{ \Priority{High} \Reason{Succeeds for user with ``add'' and ``delete'', when that user has non-name-based salt.} \Status{Implemented} } \numtest{15}{ \Priority{High} \Reason{Fails if target principal name exists.} \Status{Implemented} } \numtest{16}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{17}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \numtest{18}{ \Priority{bug fix} \Reason{Returns NO_RENAME_SALT when asked to rename a principal whose salt depends on the principal name.} \Status{Implemented} } \section{ovsec_kadm_chpass_principal} \label{ovseckadmchpassprincipal} \subsection{Quality/history enforcement tests} This section lists a series of tests which will be run a number of times, with various parameter settings (e.g., which access bits user has, whether user connected with ADMIN_SERVICE or CHANGEPW_SERVICE, etc.). The table following the list of tests gives the various parameter settings under which the tests should be run, as well which should succeed and which should fail for each choice of parameter settings. \subsubsection{List of tests} The test number of each of these tests is an offset from the base given in the table below. \numtest{1}{ \Priority{High} \Reason{With history setting of 1, change password to itself.} } \numtest{2}{ \Reason{With history setting of 2 but no password changes since principal creation, change password to itself.} } \numtest{3}{ \Reason{With history setting of 2 and one password change since principal creation, change password to itself and directly previous password.} } \numtest{4}{ \Priority{High} \Reason{With a history setting of 3 and no password changes, change password to itself.} } \numtest{5}{ \Priority{High} \Reason{With a history setting of 3 and 1 password change, change password to itself or previous password.} } \numtest{6}{ \Priority{High} \Reason{With a history setting of 3 and 2 password changes, change password to itself and the two previous passwords.} } \numtest{7}{ \Priority{High} \Reason{Change to previously unused password when now - last_pwd_change $<$ pw_min_life.} } \numtest{8}{ \Priority{High} \Reason{Change to previously unused password that doesn't contain enough character classes.} } \numtest{9}{ \Priority{High} \Reason{Change to previously unused password that's too short.} } \numtest{10}{ \Priority{High} \Reason{Change to previously unused password that's in the dictionary.} } \subsubsection{List of parameter settings} In the table below, ``7 passes'' means that test 7 above passes and the rest of the tests fail. \begin{tabular}{llllll} Base & Modify access? & Own password? & Service & Pass/Fail \\ \hline 0 & No & Yes & ADMIN & all fail \\ 20 & No & Yes & CHANGEPW & all fail \\ 40 & No & No & ADMIN & all fail \\ 60 & No & No & CHANGEPW & all fail \\ 80 & Yes & Yes & ADMIN & 7 passes \\ 100 & Yes & Yes & CHANGEPW & all fail \\ 120 & Yes & No & ADMIN & 7 passes \\ 140 & Yes & No & CHANGEPW & all fail \\ \end{tabular} \subsection{Other quality/history tests} \numtest{161}{ \Priority{High} \Reason{With history of 1, can change password to anything other than itself that doesn't conflict with other quality rules.} } \numtest{162}{ \Reason{With history of 2 and 2 password changes, can change password to original password.} } \numtest{163}{ \Priority{High} \Reason{With history of 3 and 3 password changes, can change password to original password.} } \numtest{164}{ \Priority{High} \Reason{Can change password when now - last_pwd_change $>$ pw_min_life.} } \numtest{165}{ \Priority{High} \Reason{Can change password when it contains exactly the number of classes required by the policy.} } \numtest{166}{ \Priority{High} \Reason{Can change password when it is exactly the length required by the policy.} } \numtest{167}{ \Priority{High} \Reason{Can change password to a word that isn't in the dictionary.} } \subsection{Other tests} %\numtest{168}{ %\Reason{Fails if database not initialized.} %} \numtest{169}{ \Reason{Fails for non-existent principal.} } \numtest{170}{ \Reason{Fails for null password.} } \numtest{171}{ \Priority{High} \Reason{Fails for empty-string password.} } \numtest{172}{ \Priority{High} \Reason{Pw_expiration is set to now + max_pw_life if policy exists and has non-zero max_pw_life.} } \numtest{173}{ \Priority{High} \Reason{Pw_expiration is set to 0 if policy exists and has zero max_pw_life.} } \numtest{174}{ \Priority{High} \Reason{Pw_expiration is set to 0 if no policy.} } \numtest{175}{ \Priority{High} \Reason{KRB5_KDC_REQUIRES_PWCHANGE bit is cleared when password is successfully changed.} } \numtest{176}{ \Priority{High} \Reason{Fails for user with no access bits, on other's password.} } \numtest{177}{ \Priority{High} \Reason{Fails for user with ``get'' but not ``modify'' access, on other's password.} } \numtest{178}{ \Reason{Fails for user with ``delete'' but not ``modify'' access, on other's password.} } \numtest{179}{ \Reason{Fails for user with ``add'' but not ``modify'' access, on other's password.} } \numtest{180}{ \Reason{Succeeds for user with ``get'' and ``modify'' access, on other's password.} \Status{Implemented} } \numtest{180.5}{ \Priority{High} \Reason{Succeeds for user with ``modify'' but not ``get'' access, on other's password.} \Conditions{RPC} \Status{Implemented} } \numtest{180.625}{ \Priority{High} \Reason{Fails for user with modify when connecting with CHANGEPW_SERVICE on others password} \Conditions{RPC} \Status{Implemented} } \numtest{180.75}{ \Priority{High} \Reason{Fails for user with modify when connecting with CHANGEPW_SERVICE on other's password which has expired} \Conditions{RPC} \Status{Implemented} } %\numtest{181}{ %\Reason{Password that would succeed if override_qual were false fails % if override_qual is true.} %\Expected{Returns CANNOT_OVERRIDE.} %} \numtest{182}{ \Priority{High} \Reason{Can not change key of ovsec_adm/history principal.} \Status{Implemented} } \numtest{183}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{184}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \numtest{200}{ \Version{KADM5_API_VERSION_2} \Reason{Creates a key for the principal for each unique encryption type/salt type in use.} \Status{Implemented} } \section{ovsec_kadm_chpass_principal_util} Rerun all the tests listed for ovsec_kadm_chpass_principal above in Section \ref{ovseckadmchpassprincipal}. Verify that they succeed and fail in the same circumstances. Also verify that in each failure case, the error message returned in msg_ret is as specified in the functional specification. Also, run the following additional tests. \numtest{1}{ \Reason{Null msg_ret is rejected.} } \numtest{2}{ \Priority{High} \Reason{New password is put into pw_ret, when it's prompted for.} } \numtest{3}{ \Priority{High} Reason{New password is put into pw_ret, when it's supplied by the caller.} } \numtest{4}{ \Priority{High} \Reason{Successful invocation when pw_ret is null.} } \section{ovsec_kadm_randkey_principal} \subsection{TOOSOON enforcement tests} This test should be run a number of times, as indicated in the table following it. The table also indicates the expected result of each run of the test. \test{ \Reason{Change key when now - last_pwd_change $<$ pw_min_life.} } \subsubsection{List of parameter settings} \begin{tabular}{llllll} Number & Modify Access? & Own Key? & Service & Pass/Fail & Implemented? \\ \hline 1 & No & Yes & ADMIN & fail & Yes \\ 3 & No & Yes & CHANGEPW & fail & Yes \\ 5 & No & No & ADMIN & fail \\ 7 & No & No & CHANGEPW & fail \\ 9 & Yes & Yes & ADMIN & pass \\ 11 & Yes & Yes & CHANGEPW & fail \\ 13 & Yes & No & ADMIN & pass & Yes \\ 15 & Yes & No & CHANGEPW & fail & Yes \\ \end{tabular} \subsection{Other tests} \numtest{17}{ \Reason{Fails if database not initialized.} } \numtest{18}{ \Reason{Fails for non-existent principal.} } \numtest{19}{ \Reason{Fails for null keyblock pointer.} } \numtest{20}{ \Priority{High} \Reason{Pw_expiration is set to now + max_pw_life if policy exists and has non-zero max_pw_life.} } \numtest{21}{ \Priority{High} \Reason{Pw_expiration is set to 0 if policy exists and has zero max_pw_life.} } \numtest{22}{ \Priority{High} \Reason{Pw_expiration is set to 0 if no policy.} } \numtest{23}{ \Priority{High} \Reason{KRB5_KDC_REQUIRES_PWCHANGE bit is cleared when key is successfully changed.} } \numtest{24}{ \Priority{High} \Reason{Fails for user with no access bits, on other's password.} } \numtest{25}{ \Priority{High} \Reason{Fails for user with ``get'' but not ``modify'' access, on other's password.} \Vtwonote{Change-password instead of modify access.} } \numtest{26}{ \Reason{Fails for user with ``delete'' but not ``modify'' access, on other's password.} \Vtwonote{Change-password instead of modify access.} } \numtest{27}{ \Reason{Fails for user with ``add'' but not ``modify'' access, on other's password.} \Vtwonote{Change-password instead of modify access.} } \numtest{28}{ \Reason{Succeeds for user with ``get'' and ``modify'' access, on other's password.} \Status{Implemented} \Vtwonote{Change-password instead of modify access.} } \numtest{28.25}{ \Priority{High} \Reason{Fails for user with get and modify access on others password When conneceted with CHANGEPW_SERVICE} \Status{Implemented} \Vtwonote{Change-password instead of modify access.} } \numtest{28.5}{ \Priority{High} \Reason{Succeeds for user with ``modify'' but not ``get'' access, on other's password.} \Status{Implemented} \Vtwonote{Change-password instead of modify access.} } \numtest{29}{ \Reason{The new key that's assigned is truly random. XXX not sure how to test this.} } \numtest{30}{ \Reason{Succeeds for own key, no other access bits when connecting with CHANGEPW service} \Status{Implemented} } \numtest{31}{ \Reason{Succeeds for own key, no other access bits when connecting with ADMIM service} \Status{Implemented} } \numtest{32}{ \Reason{Cannot change ovsec_adm/history key} \Status{Implemented} } \numtest{33}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{34}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \numtest{100}{ \Version{KADM5_API_VERSION_2} \Reason{Returns a key for each unique encryption type specified in the keysalts.} } \section{ovsec_kadm_get_principal} \numtest{1}{ \Reason{Fails for null ent.} \Status{Implemented} } \numtest{2}{ \Reason{Fails for non-existent principal.} \Status{Implemented} } \numtest{3}{ \Priority{High} \Reason{Fails for user with no access bits, retrieving other principal.} \Conditions{RPC} \Status{Implemented} } \numtest{4}{ \Priority{High} \Reason{Fails for user with ``add'' but not ``get'', getting principal other than his own, using ADMIN_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{5}{ \Reason{Fails for user with ``modify'' but not ``get'', getting principal other than his own, using ADMIN_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{6}{ \Reason{Fails for user with ``delete'' but not ``get'', getting principal other than his own, using ADMIN_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{7}{ \Reason{Fails for user with ``delete'' but not ``get'', getting principal other than his own, using CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{8}{ \Priority{High} \Reason{Fails for user with ``get'', getting principal other than his own, using CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{9}{ \Priority{High} \Reason{Succeeds for user without ``get'', retrieving self, using ADMIN_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{10}{ \Reason{Succeeds for user without ``get'', retrieving self, using CHANGEPW_SERVICE.} \Status{Implemented} } \numtest{11}{ \Reason{Succeeds for user with ``get'', retrieving self, using ADMIN_SERVICE.} \Status{Implemented} } \numtest{12}{ \Reason{Succeeds for user with ``get'', retrieving self, using CHANGEPW_SERVICE.} \Status{Implemented} } \numtest{13}{ \Priority{High} \Reason{Succeeds for user with ``get'', retrieving other user, using ADMIN_SERVICE.} \Status{Implemented} } \numtest{14}{ \Reason{Succeeds for user with ``get'' and ``modify'', retrieving other principal, using ADMIN_SERVICE.} \Status{Implemented} } \numtest{15}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{16}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \numtest{100}{ \Version{KADM5_API_VERSION_2} \Reason{If KADM5_PRINCIPAL_NORMAL_MASK is specified, the key_data and tl_data fields are NULL/zero.} \Status{Implemented} } \numtest{101}{ \Version{KADM5_API_VERSION_2} \Reason{If KADM5_KEY_DATA is specified, the key_data fields contain data but the contents are all NULL.} \Conditions{RPC} \Status{Implemented} } \numtest{102}{ \Version{KADM5_API_VERSION_2} \Reason{If KADM5_KEY_DATA is specified, the key_data fields contain data and the contents are all non-NULL.} \Conditions{local} \Status{Implemented} } \numtest{103}{ \Version{KADM5_API_VERSION_2} \Reason{If KADM5_TL_DATA is specified, the tl_data field contains the correct tl_data and no entries whose type is less than 256.} \Status{Implemented} } \section{ovsec_kadm_create_policy} \numtest{1}{ \Reason{Fails for mask with undefined bit set.} \Status{Implemented - untested} } \numtest{2}{ \Priority{High} \Reason{Fails if caller connected with CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{3}{ \Reason{Fails for mask without POLICY bit set.} \Status{Implemented - untested} } \numtest{4}{ \Reason{Fails for mask with REF_COUNT bit set.} \Status{Implemented} } \numtest{5}{ \Reason{Fails for invalid policy name.} \Status{Implemented - untested} } \numtest{6}{ \Priority{High} \Reason{Fails for existing policy name.} \Status{Implemented} } \numtest{7}{ \Reason{Fails for null policy name.} \Status{Implemented - untested} } \numtest{8}{ \Priority{High} \Reason{Fails for empty-string policy name.} \Status{Implemented} } \numtest{9}{ \Priority{High} \Reason{Accepts 0 for pw_min_life.} \Status{Implemented} } \numtest{10}{ \Priority{High} \Reason{Accepts non-zero for pw_min_life.} \Status{Implemented} } \numtest{11}{ \Priority{High} \Reason{Accepts 0 for pw_max_life.} \Status{Implemented} } \numtest{12}{ \Priority{High} \Reason{Accepts non-zero for pw_max_life.} \Status{Implemented} } \numtest{13}{ \Priority{High} \Reason{Rejects 0 for pw_min_length.} \Status{Implemented} } \numtest{14}{ \Priority{High} \Reason{Accepts non-zero for pw_min_length.} \Status{Implemented} } \numtest{15}{ \Priority{High} \Reason{Rejects 0 for pw_min_classes.} \Status{Implemented} } \numtest{16}{ \Priority{High} \Reason{Accepts 1 for pw_min_classes.} \Status{Implemented} } \numtest{17}{ \Priority{High} \Reason{Accepts 4 for pw_min_classes.} \Status{Implemented} } \numtest{18}{ \Priority{High} \Reason{Rejects 5 for pw_min_classes.} \Status{Implemented} } \numtest{19}{ \Priority{High} \Reason{Rejects 0 for pw_history_num.} \Status{Implemented} } \numtest{20}{ \Priority{High} \Reason{Accepts 1 for pw_history_num.} \Status{Implemented} } \numtest{21}{ \Priority{High} \Reason{Accepts 10 for pw_history_num.} \Status{Implemented} } \numtest{21.5}{ \Reason{Rejects 11 for pw_history_num.} \Status{Implemented - untested} } \numtest{22}{ \Priority{High} \Reason{Fails for user with no access bits.} \Conditions{RPC} \Status{Implemented} } \numtest{23}{ \Priority{High} \Reason{Fails for user with ``get'' but not ``add''.} \Conditions{RPC} \Status{Implemented} } \numtest{24}{ \Reason{Fails for user with ``modify'' but not ``add.''} \Conditions{RPC} \Status{Implemented - untested} } \numtest{25}{ \Reason{Fails for user with ``delete'' but not ``add.''} \Conditions{RPC} \Status{Implemented - untested} } \numtest{26}{ \Priority{High} \Reason{Succeeds for user with ``add.''} \Status{Implemented} } \numtest{27}{ \Reason{Succeeds for user with ``get'' and ``add.''} \Status{Implemented - untested} } \numtest{28}{ \Reason{Rejects null policy argument.} \Status{Implemented - untested} } \numtest{29}{ \Reason{Rejects pw_min_life greater than pw_max_life.} } \numtest{30}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{31}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \section{ovsec_kadm_delete_policy} \numtest{1}{ \Reason{Fails for null policy name.} } \numtest{2}{ \Priority{High} \Reason{Fails for empty-string policy name.} \Status{Implemented} } \numtest{3}{ \Reason{Fails for non-existent policy name.} } \numtest{4}{ \Reason{Fails for bad policy name.} } \numtest{5}{ \Priority{High} \Reason{Fails if caller connected with CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{6}{ \Priority{High} \Reason{Fails for user with no access bits.} \Conditions{RPC} \Status{Implemented} } \numtest{7}{ \Priority{High} \Reason{Fails for user with ``add'' but not ``delete''.} \Conditions{RPC} \Status{Implemented} } \numtest{8}{ \Reason{Fails for user with ``modify'' but not ``delete''.} \Conditions{RPC} } \numtest{9}{ \Reason{Fails for user with ``get'' but not ``delete.''} \Conditions{RPC} } \numtest{10}{ \Priority{High} \Reason{Succeeds for user with only ``delete''.} \Status{Implemented} } \numtest{11}{ \Reason{Succeeds for user with ``delete'' and ``add''.} } \numtest{12}{ \Priority{High} \Reason{Fails for policy with non-zero reference count.} \Status{Implemented} } \numtest{13}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{14}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \section{ovsec_kadm_modify_policy} \numtest{1}{ \Reason{Fails for mask with undefined bit set.} \Conditions{RPC} } \numtest{2}{ \Priority{High} \Reason{Fails if caller connected with CHANGEPW_SERVICE.} \Status{Implemented} } \numtest{3}{ \Reason{Fails for mask with POLICY bit set.} } \numtest{4}{ \Reason{Fails for mask with REF_COUNT bit set.} \Status{Implemented} } \numtest{5}{ \Reason{Fails for invalid policy name.} } \numtest{6}{ \Reason{Fails for non-existent policy name.} } \numtest{7}{ \Reason{Fails for null policy name.} } \numtest{8}{ \Priority{High} \Reason{Fails for empty-string policy name.} \Status{Implemented} } \numtest{9}{ \Priority{High} \Reason{Accepts 0 for pw_min_life.} \Status{Implemented} } \numtest{10}{ \Priority{High} \Reason{Accepts non-zero for pw_min_life.} \Status{Implemented} } \numtest{11}{ \Priority{High} \Reason{Accepts 0 for pw_max_life.} \Status{Implemented} } \numtest{12}{ \Priority{High} \Reason{Accepts non-zero for pw_max_life.} \Status{Implemented} } \numtest{13}{ \Priority{High} \Reason{Accepts 0 for pw_min_length.} \Status{Implemented} } \numtest{14}{ \Priority{High} \Reason{Accepts non-zero for pw_min_length.} \Status{Implemented} } \numtest{15}{ \Priority{High} \Reason{Rejects 0 for pw_min_classes.} \Status{Implemented} } \numtest{16}{ \Priority{High} \Reason{Accepts 1 for pw_min_classes.} \Status{Implemented} } \numtest{17}{ \Priority{High} \Reason{Accepts 4 for pw_min_classes.} \Status{Implemented} } \numtest{18}{ \Priority{High} \Reason{Rejects 5 for pw_min_classes.} \Status{Implemented} } \numtest{19}{ \Priority{High} \Reason{Rejects 0 for pw_history_num.} \Status{Implemented} } \numtest{20}{ \Priority{High} \Reason{Accepts 1 for pw_history_num.} \Status{Implemented} } \numtest{21}{ \Priority{High} \Reason{Accepts 10 for pw_history_num.} \Status{Implemented} } \numtest{22}{ \Priority{High} \Reason{Fails for user with no access bits.} \Conditions{RPC} \Status{Implemented} } \numtest{23}{ \Priority{High} \Reason{Fails for user with ``get'' but not ``modify''.} \Conditions{RPC} \Status{Implemented} } \numtest{24}{ \Reason{Fails for user with ``add'' but not ``modify.''} \Conditions{RPC} } \numtest{25}{ \Reason{Fails for user with ``delete'' but not ``modify.''} \Conditions{RPC} } \numtest{26}{ \Priority{High} \Reason{Succeeds for user with ``modify.''} \Status{Implemented} } \numtest{27}{ \Reason{Succeeds for user with ``get'' and ``modify.''} } \numtest{28}{ \Reason{Rejects null policy argument.} } \numtest{29}{ \Reason{Rejects change which makes pw_min_life greater than pw_max_life.} } \numtest{30}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{31}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \section{ovsec_kadm_get_policy} \numtest{1}{ \Reason{Fails for null policy.} } \numtest{2}{ \Reason{Fails for invalid policy name.} } \numtest{3}{ \Priority{High} \Reason{Fails for empty-string policy name.} \Status{Implemented} } \numtest{4}{ \Reason{Fails for non-existent policy name.} } \numtest{5}{ \Reason{Fails for null ent.} } \numtest{6}{ \Priority{High} \Reason{Fails for user with no access bits trying to get other's policy, using ADMIN_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{7}{ \Priority{High} \Reason{Fails for user with ``add'' but not ``get'' trying to get other's policy, using ADMIN_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{8}{ \Reason{Fails for user with ``modify'' but not ``get'' trying to get other's policy, using ADMIN_SERVICE.} \Conditions{RPC} } \numtest{9}{ \Reason{Fails for user with ``delete'' but not ``get'' trying to get other's policy, using ADMIN_SERVICE.} \Conditions{RPC} } \numtest{10}{ \Reason{Fails for user with ``delete'' but not ``get'' trying to get other's policy, using CHANGEPW_SERVICE.} \Conditions{RPC} } \numtest{11}{ \Priority{High} \Reason{Succeeds for user with only ``get'', trying to get own policy, using ADMIN_SERVICE.} \Status{Implemented} } \numtest{12}{ \Priority{High} \Reason{Succeeds for user with only ``get'', trying to get own policy, using CHANGEPW_SERVICE.} \Status{Implemented} } \numtest{13}{ \Reason{Succeeds for user with ``add'' and ``get'', trying to get own policy, using ADMIN_SERVICE.} } \numtest{14}{ \Reason{Succeeds for user with ``add'' and ``get'', trying to get own policy, using CHANGEPW_SERVICE.} } \numtest{15}{ \Reason{Succeeds for user without ``get'', trying to get own policy, using ADMIN_SERVICE.} } \numtest{16}{ \Priority{High} \Reason{Succeeds for user without ``get'', trying to get own policy, using CHANGEPW_SERVICE.} \Status{Implemented} } \numtest{17}{ \Priority{High} \Reason{Succeeds for user with ``get'', trying to get other's policy, using ADMIN_SERVICE.} \Status{Implemented} } \numtest{18}{ \Priority{High} \Reason{Fails for user with ``get'', trying to get other's policy, using CHANGEPW_SERVICE.} \Conditions{RPC} \Status{Implemented} } \numtest{19}{ \Reason{Succeeds for user with ``modify'' and ``get'', trying to get other's policy, using ADMIN_SERVICE.} } \numtest{20}{ \Reason{Fails for user with ``modify'' and ``get'', trying to get other's policy, using CHANGEPW_SERVICE.} } \numtest{21}{ \Priority{High} \Reason{Returns BAD_SERVER_HANDLE when a null server handle is passed in} \Status{Implemented} } \numtest{22}{ \Priority{Low} \Reason{Connects to correct server when mutliple handles exist} \Conditions{RPC} } \section{ovsec_kadm_free_principal_ent} In addition to the tests listed here, a memory-leak detector such as TestCenter, Purify or dbmalloc should be used to verify that the memory freed by this function is really freed. \numtest{1}{ \Reason{Null princ succeeds.} } \numtest{2}{ \Reason{Non-null princ succeeds.} } \section{ovsec_kadm_free_policy_ent} In addition to the tests listed here, a memory-leak detector such as TestCenter, Purify or dbmalloc should be used to verify that the memory freed by this function is really freed. \numtest{1}{ \Reason{Null policy succeeds.} } \numtest{2}{ \Reason{Non-null policy succeeds.} } \section{ovsec_kadm_get_privs} \numtest{1}{ \Reason{Fails for null pointer argument.} } This test should be run with the 16 possible combinations of access bits (since there are 4 access bits, there are $2^4 = 16$ possible combinations of them): \numtest{2}{ \Priority{High} \Reason{Returns correct bit mask for access bits of user.} \Conditions{RPC} } This test should be run locally: \numtest{3}{ \Priority{High} \Reason{Returns 0x0f.} \Conditions{local} } \end{document}