diff --git a/CASA-auth-token/java/AUTHORS b/CASA-auth-token/java/AUTHORS new file mode 100644 index 00000000..ba13017c --- /dev/null +++ b/CASA-auth-token/java/AUTHORS @@ -0,0 +1,2 @@ +Juan Carlos Luciani - jluciani@novell.com + diff --git a/CASA-auth-token/java/COPYING b/CASA-auth-token/java/COPYING new file mode 100644 index 00000000..b0ab9a23 --- /dev/null +++ b/CASA-auth-token/java/COPYING @@ -0,0 +1,459 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + diff --git a/CASA-auth-token/java/ChangeLog b/CASA-auth-token/java/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/CASA-auth-token/java/Makefile.am b/CASA-auth-token/java/Makefile.am new file mode 100644 index 00000000..84e5e7ff --- /dev/null +++ b/CASA-auth-token/java/Makefile.am @@ -0,0 +1,38 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = server package + +DIST_SUBDIRS = include server package + +EXTRA_DIST = autogen.sh + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C package $@ + +clean-local: + if [ -d lib ]; then rm -rf lib; fi + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/NEWS b/CASA-auth-token/java/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/CASA-auth-token/java/README b/CASA-auth-token/java/README new file mode 100644 index 00000000..3abc9805 --- /dev/null +++ b/CASA-auth-token/java/README @@ -0,0 +1,90 @@ +/*********************************************************************** + * + * README for auth_token + * + ***********************************************************************/ + +INTRODUCTION + +CASA-auth-token is an authentication token infrastructure with support for multiple +authentication mechanisms with an emphasis on providing a scalable single +sign-on solution. + +A key feature of auth_token is that its authentication tokens contain identity +information about the entity being authenticated. This information is made available +to the consuming services. The amount of information contained in the tokens is +configured on a per-service basis. Because of this feature, we say that CASA-auth-token +projects an "Authenticated Identity". + +ARCHITECTURE COMPONENTS + +The infrastructure provided by auth_token consists of client and server components. + +The client components of auth_token consists of a Client Engine, Get Authentication +Token API, Authentication Token Cache, and Authentication Mechanism plug-ins. + +The server components of auth_token consists of an Authentication Token Service, a +Verify Authentication Token API, a JAAS module, a PAM module, and an Apache Authentication +Provider module. The Authentication Token Service makes use of Authentication Mechanism +plug-ins, an Identity Data Store Abstraction Layer, and of Identity Token Providers. + +SECURITY FEATURES AND DATA FLOW + +Communications between the Client Engine and the Authentication Token Service (ATS) +occur over HTTPS. When a client desires to obtain an Authentication Token to access +a particular service it contacts an ATS which then proceeds to inform the client about +the Authentication Policy configured for the service. The policy contains information +about authentication mechanisms supported as well as information about the types of +credentials that the client can utilize to authenticate to the ATS. Once the client +receives the Authentication Policy, it then decides what authentication mechanism to +utilize to authenticate to the ATS based on the available authentication mechanisms +plug-ins as well as the available credentials. During the authentication process, the +ATS associates an identity with the entity being authenticated. The result of this +resolution is saved in a Session Token which is then sent to the client where it is +cached. Once the client is authenticated to the ATS, it then requests Authentication +Tokens from it using the obtained Session Token. When an ATS receives a request for +an Authentication Token, it then verifies the validity of the received Session Token +and then it creates the appropriate Identity Token for the target service which it then +embeds within the Authentication Token. The indentity information contained in the +Identity Token as well as the type of Identity Token utilized depends on what is +configured for the tatget service. + +Session Tokens and Authentication Tokens are signed by the issuing ATS using Signing +Certificates. Session Tokens and Authentication Tokens have a Lifetime Value associated +with them. Token verification involves verifying the token signatures, verifying that +the tokens where signed by a trusted entity, and verifying that the token lifetime has +not been exceeeded. + +The auth_token client/service protocol allows for the authentication of the client entity. +auth_token relies in the server authentication mechanisms of SSL to verify the identity +of the ATS. + +IMPLEMENTATION STRATEGY AND CURRENT STATUS + +auth_token is currently under development and is not ready to be used in production. +The implementation strategy has been to first complete the framework with all of its +modules, APIs, and packaging to allow application writters to start developing to it. +Once this is done, then the implementation focus will switch to completing the plumbing. + +As of this time, a lot of the framework has been completed and there are sample +applications that can be utilized to exercise it. For a more complete picture of where +we are, look at the various TODO lists present in the child folders. + +The schedule for completing auth_token is agressive. + +SECURITY CONSIDERATIONS + +CASA Authentication Tokens when compromised can be used to either impersonate +a user or to obtain identity information about the user. Because of this it is +important that the tokens be secured by applications making use of them. It is +recommended that the tokens be transmitted using SSL. + + + + + + + + + + diff --git a/CASA-auth-token/java/TODO b/CASA-auth-token/java/TODO new file mode 100644 index 00000000..4bc8d36e --- /dev/null +++ b/CASA-auth-token/java/TODO @@ -0,0 +1,17 @@ +/*********************************************************************** + * + * TODO for auth_token + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for auth_token. + +Note: There are TODO lists under each auth_token component. This file just +details outstanding items at the project level. + +OUTSTANDING ITEMS + +- Plug-in auth_token into the CASA make system. + diff --git a/CASA-auth-token/java/autogen.sh b/CASA-auth-token/java/autogen.sh new file mode 100755 index 00000000..56e0f00c --- /dev/null +++ b/CASA-auth-token/java/autogen.sh @@ -0,0 +1,130 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir +PROJECT=CASA +TEST_TYPE=-f +FILE=server/AuthTokenSvc/authtoken.settings + +DIE=0 + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile $PROJECT." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +AUTOMAKE=automake-1.9 +ACLOCAL=aclocal-1.9 + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + AUTOMAKE=automake + ACLOCAL=aclocal +} + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile $PROJECT." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +test $TEST_TYPE $FILE || { + echo "You must run this script in the top-level $PROJECT directory" + exit 1 +} + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +case $CC in +*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;; +esac + +for coin in `find $srcdir -name configure.in -print` +do + dr=`dirname $coin` + if test -f $dr/NO-AUTO-GEN; then + echo skipping $dr -- flagged as no auto-gen + else + echo processing $dr + macrodirs=`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin` + ( cd $dr + aclocalinclude="$ACLOCAL_FLAGS" + for k in $macrodirs; do + if test -d $k; then + aclocalinclude="$aclocalinclude -I $k" + ##else + ## echo "**Warning**: No such directory \`$k'. Ignored." + fi + done + if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then + if grep "sed.*POTFILES" configure.in >/dev/null; then + : do nothing -- we still have an old unmodified configure.in + else + echo "Creating $dr/aclocal.m4 ..." + test -r $dr/aclocal.m4 || touch $dr/aclocal.m4 + echo "Running gettextize... Ignore non-fatal messages." + echo "no" | gettextize --force --copy + echo "Making $dr/aclocal.m4 writable ..." + test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4 + fi + fi + if grep "^AM_GNOME_GETTEXT" configure.in >/dev/null; then + echo "Creating $dr/aclocal.m4 ..." + test -r $dr/aclocal.m4 || touch $dr/aclocal.m4 + echo "Running gettextize... Ignore non-fatal messages." + echo "no" | gettextize --force --copy + echo "Making $dr/aclocal.m4 writable ..." + test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4 + fi + if grep "^AM_GLIB_GNU_GETTEXT" configure.in >/dev/null; then + echo "Creating $dr/aclocal.m4 ..." + test -r $dr/aclocal.m4 || touch $dr/aclocal.m4 + echo "Running gettextize... Ignore non-fatal messages." + echo "no" | glib-gettextize --force --copy + echo "Making $dr/aclocal.m4 writable ..." + test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4 + fi + if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then + echo "Running libtoolize..." + libtoolize --force --copy + fi + echo "Running $ACLOCAL $aclocalinclude ..." + $ACLOCAL $aclocalinclude + if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then + echo "Running autoheader..." + autoheader + fi + echo "Running $AUTOMAKE --gnu $am_opt ..." + $AUTOMAKE --add-missing --gnu $am_opt + echo "Running autoconf ..." + autoconf + ) + fi +done + +conf_flags="--config-cache --enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c + +cd "$ORIGDIR" + +if test x$NOCONFIGURE = x; then + echo Running $srcdir/configure $conf_flags "$@" ... + $srcdir/configure $conf_flags "$@" \ + && echo Now type \`make\' to compile $PROJECT || exit 1 +else + echo Skipping configure process. +fi diff --git a/CASA-auth-token/java/configure.in b/CASA-auth-token/java/configure.in new file mode 100644 index 00000000..26afd547 --- /dev/null +++ b/CASA-auth-token/java/configure.in @@ -0,0 +1,291 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +####################################################################### + +AC_INIT(autogen.sh) +AC_CANONICAL_SYSTEM +AM_INIT_AUTOMAKE(CASA_auth_token, 0.1.1) +RELEASE=`date +%Y%m%d_%H%M` +AC_SUBST(RELEASE) +AM_MAINTAINER_MODE + +# +# Check for a valid C# compiler +# +#AC_CHECK_PROG(CSC, csc, csc) +#test -z "$CSC" && AC_CHECK_PROG(CSC, mcs, mcs) +#test -z "$CSC" && AC_MSG_ERROR([no acceptable C Sharp compiler found in \$PATH]) + +# +# Check for valid C# compiler in linux +# +case $host_os in + cygwin*) + ;; + *) + AC_CHECK_PROG(CSC, csc, csc) + test -z "$CSC" && AC_CHECK_PROG(CSC, mcs, mcs) + test -z "$CSC" && AC_MSG_ERROR([no acceptable C Sharp compiler found in \$PATH]) + + ;; +esac + +case $CSC in + # + # Mono-specific configuration + # + mcs) + CSC_EXEFLAG=/target:exe + CSC_LIBFLAG=/target:library + CSC_EXEFLAG=/target:exe + CSC_WINEXEFLAG=/target:winexe + CSCFLAGS='/d:MONO /warn:4 /d:TRACE -d:LINUX' + CSCFLAGS_DEBUG="/debug+ /d:DEBUG" + CSCFLAGS_OPTIMIZE="/optimize+" + MONO=mono + MONO_DEBUG='mono --debug' + MONO_PATH= + SYSTEM_XML='System.Xml.dll' + ;; + # + # .NET-specific configuration + # + csc) + CSC_EXEFLAG=/target:exe + CSC_LIBFLAG=/target:library + CSC_EXEFLAG=/target:exe + CSC_WINEXEFLAG=/target:winexe + CSCFLAGS='/d:DOTNET /warn:4 /d:TRACE /nologo' + CSCFLAGS_DEBUG="/debug+ /d:DEBUG" + CSCFLAGS_OPTIMIZE="/optimize+" + MONO= + MONO_DEBUG= + MONO_PATH= + SYSTEM_XML='System.XML.dll' + ;; +esac + +AC_SUBST(CSC) +AC_SUBST(CSC_EXEFLAG) +AC_SUBST(CSC_LIBFLAG) +AC_SUBST(CSC_WINEXEFLAG) +AC_SUBST(CSCFLAGS) +AC_SUBST(CSCFLAGS_DEBUG) +AC_SUBST(MONO) +AC_SUBST(MONO_PATH) +AC_SUBST(SYSTEM_XML) + +SRCDIR='$(top_srcdir)' +DOCDIR="$SRCDIR/doc" +TOOLDIR='$(top_srcdir)/tools' +AC_SUBST(SRCDIR) +AC_SUBST(DOCDIR) +AC_SUBST(TOOLDIR) +EMPTY= +SPACE='$(EMPTY) $(EMPTY)' + +AC_SUBST(EMPTY) +AC_SUBST(SPACE) + +# +# Check for operating system and set TARGET_OS +# +case $host_os in + cygwin*) + TARGET_OS='windows' + ;; + *) + TARGET_OS='linux' + ;; +esac + +AC_SUBST(TARGET_OS) +AM_CONDITIONAL(LINUX, test "$TARGET_OS" = "linux") +AM_CONDITIONAL(WINDOWS, test "$TARGET_OS" = "windows") + +# +# Check for architecture and set TARGET_ARCH +# ia64 needs to be treated as non64. + +case $target_cpu in + x86_64|p*pc64|s390x) + LIB=lib64 + ;; + *ia64|*) + LIB=lib + ;; +esac + +AC_SUBST(LIB) +AM_CONDITIONAL(LIB64, test "$LIB" = lib64) + +# +# +# Set platform-specific variables +# +case $TARGET_OS in + # + # Linux-specific configuration + # + linux) + # + # Set variables + # + COMMON_CLEAN_FILES='' + ICON_EXT='.ico' + ICON_FLAG='/resource:' + PLATFORM_SUBDIRS=$LINUX_SUBDIRS + SEP='/' + LINK=gcc + ;; + # + # Windows-specific configuration + # + windows) + COMMON_CLEAN_FILES='*.suo */*.suo *.csproj.user */*.csproj.user bin obj */bin */obj *.xml */*.xml *.pdb */*.pdb' + ICON_EXT='.ico' + ICON_FLAG='/win32icon:' + PLATFORM_SUBDIRS=$WINDOWS_SUBDIRS + SEP='$(EMPTY)\\$(EMPTY)' + LINK=link.exe + ;; +esac +AC_SUBST(COMMON_CLEAN_FILES) +AC_SUBST(ICON_EXT) +AC_SUBST(ICON_FLAG) +AC_SUBST(PLATFORM_SUBDIRS) +AC_SUBST(SEP) +AC_SUBST(LINK) + +# +# Run standard macros +# +AM_PROG_CC_STDC +AC_PROG_INSTALL +AC_HEADER_STDC + +####### +# +# set CFLAGS +# +case $host_os in + linux*) + CFLAGS="$CFLAGS" + ;; + cygwin*) + CC=cl.exe + CFLAGS="-D WIN32 -D SSCS_WIN32_PLAT_F -D N_PLAT_CLIENT -MT -Ox" + ;; +esac + +# +# Handle --enable-debug +# +AC_ARG_ENABLE(debug, [ + --enable-debug configure the Makefiles to build in DEBUG mode], + [case "${enableval}" in + yes) enable_debug=true ;; + no) enable_debug=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; + esac],[enable_debug=false]) +AM_CONDITIONAL(DEBUG, test x$enable_debug = xtrue) +if test "$enable_debug" = "true" +then + # Build debug version. + # CFLAGS="$CFLAGS_DEBUG $CFLAGS -DDBG -DDEBUG" + CFLAGS="$CFLAGS_DEBUG $CFLAGS -g -DDBG -DDEBUG \ +-fPIC -DPIC -DSSCS_LINUX_PLAT_F -O2 -fmessage-length=0 -Wall \ +-D_REENTRANT -DALIGNMENT -DN_PLAT_UNIX \ +-DUNIX -DLINUX -DIAPX38" + CSCFLAGS="$CSCFLAGS_DEBUG $CSCFLAGS" + CXXFLAGS="$CXXFLAGS_DEBUG $CXXFLAGS" + DEVENV_CONFIGURATION=Debug + MONO=$MONO_DEBUG +else + # Build optimized version. + CFLAGS="$CFLAGS_OPTIMIZE $CFLAGS -g -fPIC -DPIC \ +-DSSCS_LINUX_PLAT_F -O2 -fmessage-length=0 -Wall \ +-D_REENTRANT -DALIGNMENT -DN_PLAT_UNIX \ +-DUNIX -DLINUX -DIAPX38" + CSCFLAGS="$CSCFLAGS_OPTIMIZE $CSCFLAGS" + CXXFLAGS="$CXXFLAGS_OPTIMIZE $CXXFLAGS" + DEVENV_CONFIGURATION=Release +fi +AC_SUBST(CSCFLAGS) +AC_SUBST(DEVENV_CONFIGURATION) + +##comment out due to build failure +# Check for GCC version to add fstack-protector flag +# +#GCC_VER="`gcc -dumpversion`" +#case "$GCC_VER" in +# 3*) +# ;; +# 4*) +# CFLAGS="$CFLAGS -fstack-protector" +# ;; +# *) +# ;; +#esac + +AC_SUBST(GCC_VER) + +# +# Configure PKG_CONFIG +# +AC_PATH_PROG(PKG_CONFIG, pkg-config, no) +if test "x$PKG_CONFIG" = "xno"; then + AC_MSG_ERROR([You need to install pkg-config]) +fi + +# +# Configure files +# +AC_OUTPUT([ +Makefile +package/Makefile +package/linux/Makefile +package/linux/CASA-auth-token-service.spec +include/Makefile +server/Makefile +server/AuthTokenValidate/Makefile +server/AuthTokenValidate/linux/Makefile +server/AuthTokenValidate/idenTokenProviders/Makefile +server/AuthTokenValidate/idenTokenProviders/casa/Makefile +server/AuthTokenValidate/idenTokenProviders/casa/linux/Makefile +server/PamSupport/Makefile +server/PamSupport/linux/Makefile +server/ApacheSupport/Makefile +server/ApacheSupport/2.2/Makefile +server/ApacheSupport/2.2/linux/Makefile +server/AuthTokenSvc/Makefile +server/AuthTokenSvc/src/Makefile +server/AuthTokenSvc/src/com/Makefile +server/AuthTokenSvc/src/com/novell/Makefile +server/AuthTokenSvc/src/com/novell/casa/Makefile +server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Makefile +server/JaasSupport/Makefile +server/JaasSupport/src/Makefile +server/JaasSupport/src/com/Makefile +server/JaasSupport/src/com/novell/Makefile +server/JaasSupport/src/com/novell/casa/Makefile +server/JaasSupport/src/com/novell/casa/jaas/Makefile +]) + diff --git a/CASA-auth-token/java/package/Makefile.am b/CASA-auth-token/java/package/Makefile.am new file mode 100644 index 00000000..f6a6d745 --- /dev/null +++ b/CASA-auth-token/java/package/Makefile.am @@ -0,0 +1,38 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = linux + +DIST_SUBDIRS = linux + +EXTRA_DIST = + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +clean-local: + if [ -d lib ]; then rm -rf lib; fi + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/package/linux/CASA-auth-token-service.spec.in b/CASA-auth-token/java/package/linux/CASA-auth-token-service.spec.in new file mode 100644 index 00000000..8d62cad7 --- /dev/null +++ b/CASA-auth-token/java/package/linux/CASA-auth-token-service.spec.in @@ -0,0 +1,312 @@ +# +# spec file for the CASA-auth-token packages. +# +# Copyright (c) 2006 SUSE LINUX Products GmbH, Nuernberg, Germany. +# This file and all modifications and additions to the pristine +# package are under the same license as the package itself. +# +# Please submit bugfixes or comments via http://bugs.opensuse.org +# + +# norootforbuild + +# For debug build, please replace Release to Debug and set debug_opt to --enable-debug +%define cfg Release +%define debug_opt "" + + +Name: @PACKAGE@ +URL: http://www.novell.com/products +BuildRequires: libstdc++ libgcc gcc-c++ glib2-devel krb5-devel libgssapi libstdc++-devel pam-devel pkgconfig java-1_5_0-ibm-devel apache2-devel update-alternatives mono-devel CASA-devel servletapi5 identity-abstraction +%define prefix /usr +%define jprefix /usr/share/java +License: LGPL +Group: Applications/System +Autoreqprov: on +%define bldno 1.0.0 +Version: @VERSION@ +Release: 0 +Summary: Novell Common Authentication Services Adapter Authentication Token Infrastructure (CASA-auth-token) +Source: %{name}-%{version}.tar.bz2 +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Requires: java-1_5_0-ibm servletapi5 tomcat5 +PreReq: %fillup_prereq %insserv_prereq + +%description +CASA-auth-token is an authentication token infrastructure with support for multiple +authentication mechanisms with an emphasis on providing a scalable single +sign-on solution. + +A key feature of CASA-auth-token is that its authentication tokens contain identity +information about the entity being authenticated. This information is made available +to the consuming services. The amount of information contained in the tokens is +configured on a per-service basis. Because of this feature, we say that CASA-auth-token +projects an "Authenticated Identity". + +The CASA-auth-token-service is the infrastructure component responsible for authenticating +entities using the native authentication mechanism and for issuing tokens that can later +be used by applications to authenticate the entity o services that are CASA authentication +enabled. + +%package -n CASA-auth-token-server-support +Summary: Libraries needed for "C" applications development. +Group: Applications/System +Requires: CASA-devel + +%description -n CASA-auth-token-server-support +This package contains the CASA (Common Authentication Services Adapter) +authentication token infrastructure lower level libraries for token +verification from native code ("C"). It is recomended that this library +not be invoked directly by applications, instead it is recomended that +appplication invoke its services through the support modules provided to +integrate with PAM or the Apache Web Server. + +%package -n CASA-auth-token-pam-support +Summary: Libraries needed for PAM applications development. +Group: Applications/System +Requires: CASA-auth-token-server-support pam + +%description -n CASA-auth-token-pam-support +This package contains the CASA (Common Authentication Services Adapter) +authentication token infrastructure PAM module for token verification. + +%package -n CASA-auth-token-apache2_2-support +Summary: Libraries needed for Apache 2.2 applications development. +Group: Applications/System +Requires: apache2 CASA-auth-token-server-support + +%description -n CASA-auth-token-apache2_2-support +This package contains the CASA (Common Authentication Services Adapter) +authentication token infrastructure Apache v2.2 authentication provider +module for token verification. The module expects that users authenticate +utilizing the HTTP Basic authentication scheme and that the password utilized consist +of a CASA authentication token. Information about the authenticated identity is +made available to other Apache modules via the Apache request environment variable. + +%package -n CASA-auth-token-jaas-support +Summary: Libraries needed for JAAS applications development. +Group: Applications/System +Requires: java-1_5_0-ibm + +%description -n CASA-auth-token-jaas-support +This package contains the CASA (Common Authentication Services Adapter) +authentication token infrastructure JAAS module and supporting libraries +for token verification. + +%package -n CASA-auth-token-devel +Summary: Include files needed for applications development. +Group: Applications/System +Requires: CASA-devel CASA-auth-token-server-support CASA-auth-token-jaas-support CASA-auth-token-pam-support CASA-auth-token-apache2_2-support CASA-auth-token-service + +%description -n CASA-auth-token-devel +This package contains the files necessary for the development of client and +server applications that utilize the CASA (Common Authentication Service Adapter) +authentication token infrastructure for authentication. + + +%prep +%setup -q +#%patch +%if %{_lib} == "lib64" +%define binsource bin64 +%else +%define binsource bin +%endif + +%build +export PATH=.:$PATH:/usr/%_lib/qt3/bin +%if %suse_version > 1000 +export CFLAGS="$CFLAGS $RPM_OPT_FLAGS -fstack-protector" +%endif + +./autogen.sh +make + + +%install + +## Prime the file system ## +install -d %{buildroot}%{prefix} +install -d %{buildroot}%{prefix}/%{_lib} +install -d %{buildroot}%{prefix}/%{_lib}/security +install -d %{buildroot}%{prefix}/include +install -d %{buildroot}%{prefix}/share +install -d %{buildroot}%{prefix}/share/java + +## CASA-auth-token-service ## +# Libs +install -m 755 %{_lib}/java/CasaAuthTokenSvc.war %{buildroot}%{prefix}/share/java/CasaAuthTokenSvc.war.%{bldno} + +# Lib Symbolic Links +ln -sf CasaAuthTokenSvc.war.%{bldno} %{buildroot}%{prefix}/share/java/CasaAuthTokenSvc.war +ln -sf CasaAuthTokenSvc.war.%{bldno} %{buildroot}%{prefix}/share/java/CasaAuthTokenSvc.war.1 + +## CASA-auth-token-server-support ## +# Libs +install -m 755 %{_lib}/%{cfg}/libcasa_s_authtoken.so %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so.%{bldno} + +# Lib Symbolic Links +ln -sf libcasa_s_authtoken.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so +ln -sf libcasa_s_authtoken.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so.1 + +## CASA-auth-token-pam-support ## +# Libs +install -m 755 %{_lib}/%{cfg}/pam_casaauthtok.so %{buildroot}%{prefix}/%{_lib}/security/pam_casaauthtok.so.%{bldno} +#install -m 755 %{_lib}/%{cfg}/pam_casaauthtok.so %{buildroot}%{prefix}/%{_lib}/security/pam_casaauthtok.so + +# Lib Symbolic Links +ln -sf pam_casaauthtok.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/security/pam_casaauthtok.so +ln -sf pam_casaauthtok.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/security/pam_casaauthtok.so.1 + +## CASA-auth-token-apache2_2-support ## +# Libs +install -m 755 %{_lib}/%{cfg}/mod_authn_casa.so %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so.%{bldno} + +# Lib Symbolic Links +ln -sf mod_authn_casa.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so +ln -sf mod_authn_casa.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so.1 + +## CASA-auth-token-jaas-support ## +# Libs +install -m 755 %{_lib}/java/CasaJaasSupport.jar %{buildroot}%{prefix}/share/java/CasaJaasSupport.jar.%{bldno} +install -m 755 %{_lib}/java/CasaAuthToken.jar %{buildroot}%{prefix}/share/java/CasaAuthToken.jar.%{bldno} + +# Lib Symbolic Links +ln -sf CasaJaasSupport.jar.%{bldno} %{buildroot}%{prefix}/share/java/CasaJaasSupport.jar +ln -sf CasaJaasSupport.jar.%{bldno} %{buildroot}%{prefix}/share/java/CasaJaasSupport.jar.1 +ln -sf CasaAuthToken.jar.%{bldno} %{buildroot}%{prefix}/share/java/CasaAuthToken.jar +ln -sf CasaAuthToken.jar.%{bldno} %{buildroot}%{prefix}/share/java/CasaAuthToken.jar.1 + +## CASA-auth-token-devel ## +# Header Files +install -m 644 include/casa_c_authtoken.h %{buildroot}%{prefix}/include +install -m 644 include/casa_s_authtoken.h %{buildroot}%{prefix}/include + + +%clean +rm -rf $RPM_BUILD_ROOT + + +## CASA-auth-token-service ## +%pre +# Nothing to do in this pre script + +%post +/sbin/ldconfig + +%preun +# Nothing to do in this preun script + +%postun +# Nothing to do in this postun script + +%files +%defattr(-,root,root) +%{prefix}/share/java/CasaAuthTokenSvc.war.%{bldno} +%{prefix}/share/java/CasaAuthTokenSvc.war +%{prefix}/share/java/CasaAuthTokenSvc.war.1 + + +## CASA-auth-token-server-support ## +%pre -n CASA-auth-token-server-support +# Nothing to do in this pre script + +%post -n CASA-auth-token-server-support +/sbin/ldconfig + +%preun -n CASA-auth-token-server-support +# Nothing to do in this preun script + +%postun -n CASA-auth-token-server-support +# Nothing to do in this postun script + +%files -n CASA-auth-token-server-support +%defattr(-,root,root) +%{prefix}/%{_lib}/libcasa_s_authtoken.so.%{bldno} +%{prefix}/%{_lib}/libcasa_s_authtoken.so +%{prefix}/%{_lib}/libcasa_s_authtoken.so.1 + + +## CASA-auth-token-pam-support ## +%pre -n CASA-auth-token-pam-support +# Nothing to do in this pre script + +%post -n CASA-auth-token-pam-support +/sbin/ldconfig + +%preun -n CASA-auth-token-pam-support +# Nothing to do in this preun script + +%postun -n CASA-auth-token-pam-support +# Nothing to do in this postun script + +%files -n CASA-auth-token-pam-support +%defattr(-,root,root) +%dir %{prefix}/%{_lib}/security +%{prefix}/%{_lib}/security/pam_casaauthtok.so.%{bldno} +%{prefix}/%{_lib}/security/pam_casaauthtok.so +%{prefix}/%{_lib}/security/pam_casaauthtok.so.1 + + +## CASA-auth-token-apache2_2-support ## +%pre -n CASA-auth-token-apache2_2-support +# Nothing to do in this pre script + +%post -n CASA-auth-token-apache2_2-support +/sbin/ldconfig + +%preun -n CASA-auth-token-apache2_2-support +# Nothing to do in this preun script + +%postun -n CASA-auth-token-apache2_2-support +# Nothing to do in this postun script + +%files -n CASA-auth-token-apache2_2-support +%defattr(-,root,root) +%{prefix}/%{_lib}/mod_authn_casa.so.%{bldno} +%{prefix}/%{_lib}/mod_authn_casa.so +%{prefix}/%{_lib}/mod_authn_casa.so.1 + + +## CASA-auth-token-jaas-support ## +%pre -n CASA-auth-token-jaas-support +# Nothing to do in this pre script + +%post -n CASA-auth-token-jaas-support +/sbin/ldconfig + +%preun -n CASA-auth-token-jaas-support +# Nothing to do in this preun script + +%postun -n CASA-auth-token-jaas-support +# Nothing to do in this postun script + +%files -n CASA-auth-token-jaas-support +%defattr(-,root,root) +%{prefix}/share/java/CasaJaasSupport.jar.%{bldno} +%{prefix}/share/java/CasaJaasSupport.jar +%{prefix}/share/java/CasaJaasSupport.jar.1 +%{prefix}/share/java/CasaAuthToken.jar.%{bldno} +%{prefix}/share/java/CasaAuthToken.jar +%{prefix}/share/java/CasaAuthToken.jar.1 + + +## CASA-auth-token-devel ## +%pre -n CASA-auth-token-devel +# Nothing to do in this pre script + +%post -n CASA-auth-token-devel +# Nothing to do in this post script + +%preun -n CASA-auth-token-devel +# Nothing to do in this preun script + +%postun -n CASA-auth-token-devel +# Nothing to do in this postun script + +%files -n CASA-auth-token-devel +%defattr(-,root,root) +%{prefix}/include/casa_c_authtoken.h +%{prefix}/include/casa_s_authtoken.h + +%changelog -n CASA-auth-token diff --git a/CASA-auth-token/java/package/linux/Makefile.am b/CASA-auth-token/java/package/linux/Makefile.am new file mode 100644 index 00000000..7eaa5b7f --- /dev/null +++ b/CASA-auth-token/java/package/linux/Makefile.am @@ -0,0 +1,67 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +####################################################################### +#how do you get the version?? +RPM_FILE = $(PACKAGE)-$(VERSION)-$(RELEASE).$(target_cpu).rpm +#SRPM_FILE = $(PACKAGE)-$(VERSION)-$(RELEASE).src.rpm +SRPM_FILE = $(PACKAGE)-$(VERSION)*.src.rpm + +SPEC_FILE = CASA-auth-token-service.spec + +.PHONY: package package-clean package-install package-uninstall casa + +#all: $(RPM_FILE) + +package: $(RPM_FILE) + +all clean: + +$(RPM_FILE): + cd $(top_srcdir); make dist-bzip2 + rm -rf RPM + mkdir RPM + echo %_topdir `pwd`/RPM > $(HOME)/.rpmmacros + mkdir -p RPM/BUILD + mkdir -p RPM/RPMS + mkdir -p RPM/SOURCES + mkdir -p RPM/SPECS + mkdir -p RPM/SRPMS + cp $(SPEC_FILE) RPM/SPECS + cp $(top_srcdir)/$(PACKAGE)-*.tar.bz2 RPM/SOURCES + mv $(top_srcdir)/$(PACKAGE)-$(VERSION).tar.bz2 $(PACKAGE)-$(VERSION).tar.bz2 + rpmbuild -ba -v -vv --target=$(target_triplet) RPM/SPECS/$(SPEC_FILE) + cp RPM/RPMS/*/*.rpm . + cp RPM/SRPMS/$(SRPM_FILE) . + +package-install: package + su -c "rpm -Uvh $(RPM_FILE)" + +package-uninstall: + su -c "rpm -e $(PACKAGE)" + +package-clean clean-local: + rm -rf *.rpm RPM *.bz2 + +distclean-local: package-clean + rm -f Makefile $(SPEC_FILE) + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/.project b/CASA-auth-token/java/server/AuthTokenSvc/.project new file mode 100644 index 00000000..a5fb4a20 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/.project @@ -0,0 +1,42 @@ + + + CasaAuthServer + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.jst.j2ee.ejb.annotations.xdoclet.xdocletbuilder + + + + + + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.jdt.core.javanature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jem.workbench.JavaEMFNature + + + + identity-abstraction.jar + 1 + /home/jluciani/dev-local/bandit/trunk/IdentityAbstraction/build/identity-abstraction.jar + + + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/Makefile.am b/CASA-auth-token/java/server/AuthTokenSvc/Makefile.am new file mode 100644 index 00000000..74d7ce0b --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/Makefile.am @@ -0,0 +1,141 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +####################################################################### + +SUBDIRS = src +DIST_SUBDIRS = src + +EXTRA_DIST = authtoken.settings \ + identoken.settings \ + README \ + svc.settings \ + TODO \ + web.xml + +ROOT = ../.. + +LIBDIR = $(ROOT)/$(LIB) + +IDENT_ABSTRACTION_DIR = /usr/share/java/identity-abstraction +IDENT_ABSTRACTION_DEPENDANCIES_DIR = /usr/share/java/identity-abstraction/dependancies + +JAVAROOT = . +JAVAC= javac + +WEBAPP_NAME = CasaAuthTokenSvc +WEBAPP_EXT = war +MODULE_NAME = CasaAuthToken +MODULE_EXT = jar + +JAVAFILES = src/com/novell/casa/authtoksvc/ProtoDefs.java \ + src/com/novell/casa/authtoksvc/AuthMechConfig.java \ + src/com/novell/casa/authtoksvc/SvcConfig.java \ + src/com/novell/casa/authtoksvc/IdenTokenConfig.java \ + src/com/novell/casa/authtoksvc/AuthTokenConfig.java \ + src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java \ + src/com/novell/casa/authtoksvc/AuthMechanism.java \ + src/com/novell/casa/authtoksvc/Authenticate.java \ + src/com/novell/casa/authtoksvc/RpcMethod.java \ + src/com/novell/casa/authtoksvc/Rpc.java \ + src/com/novell/casa/authtoksvc/GetAuthPolicy.java \ + src/com/novell/casa/authtoksvc/Base64Coder.java \ + src/com/novell/casa/authtoksvc/AuthReqMsg.java \ + src/com/novell/casa/authtoksvc/AuthRespMsg.java \ + src/com/novell/casa/authtoksvc/IdentityToken.java \ + src/com/novell/casa/authtoksvc/CasaIdentityToken.java \ + src/com/novell/casa/authtoksvc/AuthToken.java \ + src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java \ + src/com/novell/casa/authtoksvc/GetAuthPolicyRespMsg.java \ + src/com/novell/casa/authtoksvc/GetAuthToken.java \ + src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java \ + src/com/novell/casa/authtoksvc/GetAuthTokRespMsg.java \ + src/com/novell/casa/authtoksvc/Krb5Authenticate.java \ + src/com/novell/casa/authtoksvc/PwdAuthenticate.java \ + src/com/novell/casa/authtoksvc/SessionToken.java + +BUILDDIR = build + +WEBAPP = $(WEBAPP_NAME).$(WEBAPP_EXT) + +AUTHTOKEN_FILES = -C $(BUILDDIR)/webapp/WEB-INF/classes com + +CLASSES = $(addprefix $(BUILDDIR)/, $(JAVAFILES:%.java=%.class)) + +LIBS = /usr/share/java/servletapi5.jar +CLASSPATH = $(IDENT_ABSTRACTION_DIR)/identity-abstraction.jar:$(LIBS) + +CUR_DIR := $(shell pwd) + +all: $(BUILDDIR)/$(WEBAPP) $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) + +$(BUILDDIR)/%.class: %.java + @echo [======== Compiling $@ ========] + $(JAVAC) -sourcepath src -classpath $(CLASSPATH) -d $(BUILDDIR)/webapp/WEB-INF/classes $< + +$(BUILDDIR)/$(WEBAPP): $(BUILDDIR) $(CLASSES) + @echo [======== Creating Webapp $@ ========] + cp web.xml $(BUILDDIR)/webapp/WEB-INF/web.xml + cp svc.settings $(BUILDDIR)/webapp/WEB-INF/conf/svc.settings + cp authtoken.settings $(BUILDDIR)/webapp/WEB-INF/conf/authtoken.settings + cp identoken.settings $(BUILDDIR)/webapp/WEB-INF/conf/identoken.settings + cp src/com/novell/casa/authtoksvc/Krb5_mechanism.settings $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/Krb5Authenticate/mechanism.settings + cp src/com/novell/casa/authtoksvc/Pwd_mechanism.settings $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/PwdAuthenticate/mechanism.settings + cp $(IDENT_ABSTRACTION_DIR)/*.jar $(BUILDDIR)/webapp/WEB-INF/lib/ + cp $(IDENT_ABSTRACTION_DEPENDANCIES_DIR)/*.jar $(BUILDDIR)/webapp/WEB-INF/lib/ + jar cvf $(BUILDDIR)/$(WEBAPP) -C $(BUILDDIR)/webapp . + cp $(BUILDDIR)/$(WEBAPP) $(LIBDIR)/java/ + +$(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT): $(BUILDDIR) $(CLASSES) + @echo [======== Jarring $@ ========] + jar cvf $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) $(AUTHTOKEN_FILES) + cp $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/java/ + +$(BUILDDIR): + [ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) + [ -d $(BUILDDIR)/webapp ] || mkdir -p $(BUILDDIR)/webapp + [ -d $(BUILDDIR)/webapp/WEB-INF ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF + [ -d $(BUILDDIR)/webapp/WEB-INF/classes ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/classes + [ -d $(BUILDDIR)/webapp/WEB-INF/lib ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/lib + [ -d $(BUILDDIR)/webapp/WEB-INF/conf ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf + [ -d $(BUILDDIR)/webapp/WEB-INF/conf/enabled_services ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/enabled_services + [ -d $(BUILDDIR)/webapp/WEB-INF/conf/auth_mechanisms ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/auth_mechanisms + [ -d $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms + [ -d $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/Krb5Authenticate ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/Krb5Authenticate + [ -d $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/PwdAuthenticate ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/PwdAuthenticate + [ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) + [ -d $(LIBDIR)/java ] || mkdir -p $(LIBDIR)/java + +install-exec-local: + +uninstall-local: + +#installcheck-local: install + +clean-local: + if [ -d $(BUILDDIR) ]; then rm -rf $(BUILDDIR); fi + if [ -f $(LIBDIR)/java/$(MODULE_NAME).$(MODULE_EXT) ]; then rm -f $(LIBDIR)/java/$(MODULE_NAME).$(MODULE_EXT); fi + if [ -f $(LIBDIR)/java/$(WEBAPP) ]; then rm -f $(LIBDIR)/java/$(WEBAPP); fi + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + rm -f Makefile + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/README b/CASA-auth-token/java/server/AuthTokenSvc/README new file mode 100644 index 00000000..6b83201b --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/README @@ -0,0 +1,292 @@ +/*********************************************************************** + * + * README for AuthTokenSvc + * + ***********************************************************************/ + +INTRODUCTION + +AuthTokenSvc is the CASA Authentication Token Service (ATS). It is implemented +as a Java servlet and supporting classes that execute in the Tomcat environment. + +The ATS is responsible for providing clients with the necessary authentication +policy information, for authenticating client entities, and for providing +clients with Authentication Tokens that they can then use for authenticating +to CASA Authentication enabled services. + +The ATS utilizes mechanism plug-ins for authenticating client entities as well +Identity Token Providers for the generation of Identity Tokens. + +ENVIRONMENT SETTINGS + +The following options must be set in the JAVA_OPTS setting before starting Tomcat +to allow the Kerberos authentication mechanism to work properly: + +-Djavax.security.auth.useSubjectCredsOnly=false +-Djava.security.auth.login.config={replace with the path for JAAS configuration + file for the service} + +After setting the above values in the JAVA_OPTS variable you must export it for +Tomcat to be able to make use of it. + +The following entry should be included in the JAAS configuration file specified +in the java.security.auth.login.config option above to enable the Krb5 authentication +mechanism to work correctly: + +other { +com.sun.security.auth.module.Krb5LoginModule required + useTicketCache=true + ticketCache="/var/cache/tomcat5/base/temp/ticket.cache" + useKeyTab=true + principal="host/server.company.com" + doNotPrompt=true + storeKey=true + keyTab="/etc/krb5.keytab"; +} + +Please adjust the ticketCache and principal setting to match your installation. + +CONFIGURATION + +AuthTokenSvc configuration consists of multiple entities. Most of the AuthTokenSvc +configuration is contained within the "conf" folder under the WEB-INF folder of the +application. For an example configuration setup for the AuthTokenSvc see the +sampleConf folder. + +The location of the AuthTokenSvc configuration folder can be over-ridden by specifying +a different path via the com.novell.casa.authtoksvc.config system property. + +CONFIGURING THE BASE SERVICE + +The ATS base settings are configured in the svc.settings file under the conf folder. + +Thhe following is an example svc.settings file: + + + + 43200 + 10 + /home/jluciani/jakarta-tomcat-5.0.28/webapps/CasaAuthTokenSvc/WEB-INF/conf/iaRealms.xml + 60 + o=novell + + +Note the following about the sample svc.settings file: + +- The settngs that you can specify in the svc.settings file are: SessionLifetime, + LifetimeShorter, IAConfigFile, and startSearchContext. + +- The SessionTokenLifetime setting specifies the number of seconds for which a + session token is good for after being issued. The default value for this setting + is 43200 seconds. Note that a larger value reduces overhead. + +- The LifetimeShorter setting specifies the number of seconds that should be substracted + from the SessionTokenLifetime when calculating the number of seconds that clients are + told that the session tokens are good for. The default value for this setting is 5 + seconds. + +- The IAConfigFile settings specifies the path to the identity abstraction + configuration file. The identity abstraction configuration file configures + the different realms (contexts) that the ATS can utilize to authenticate + entities and resolve identities. In the future the configuration of this + settng will be optional. + +- The ReconfigureInterval setting specifies how often the ATS should refresh its + configuration. The default value for this setting is 60 seconds. A ReconfigureInterval + value of 0 means that the ATS will not refresh its configuration once it has been + initialized, thus requiring that the servlet be re-initialized to make configuration + changes take effect. + +- The startSearchContext setting specifies the begin location for initiating + context searches. The absence of this setting will result in searches ocurring + from the root of the tree. This setting or an equivalent setting will be moved + to the identity abstraction configuration file where it belongs. Once this is done, + the setting will no longer be recognized within the svc.settings file. + +CONFIGURING SERVICES TO CONSUME CASA AUTHENTICATION TOKENS + +Services are configured to consume CASA authentication tokens by creating folders +under the conf/enabled_services folders. Since CASA distinguishes between services +of the same name existing in different hosts, the first folder that must be created +is one for the host where the service resides. The host folder name must match the +DNS name of the host where the service resides. Services are configured by creating +a folder under the appropriate host folder with a name matching the service name. + +Note when configuring services that the service name and the host names must match +the service and host names specified by the client applications when requesting +tokens to authenticate to them. + +The services folder must contain an auth.policy file, an authtoken.settings file, +and an identoken.settings file. In the absence of any one of those files, the ATS +will default to utilizing the files present under its conf folder. + +The auth.policy file specifies the authentication realms (or contexts) to which +entities can authenticate to gain access to the service. The auth.policy file also +specifies the authentication mechanisms that can be utilized to authenticate to the +realms. + +The following is an example auth.policy file: + + + + + CorpTree + Krb5Authenticate + host@tokenserver.company.novell.com + + + CorpTree + PwdAuthenticate + + + + +Note the following about the sample auth.policy file: + +- An authentication realm is specified in the auth.policy file by creating an + auth_policy entry for it. An auth_policy entry must contain the realm name along + with the entries for the authentication mechanisms. + +- When a realm supports more than one authentication mechanism, you must create + an auth_source entry for each supported mechanism. + +- The realm names correspond to the realmIDs configured in the Identity Abstraction + configuration file for the desired context entry. + +- The authentication mechanism entries are: mechanism and mechanism_info. The mechanism + entry specifies the name of the authentication mechanism. The mechanism_info specifies + some mechanism specific information. Both authentication mechanism entries must be + specified for an auth_source entry. + +- The name of the Krb5 Authentication mechanism is "Krb5Authenticate". This mechanism + requires that you specify the service's kerberos principal name under the mechanism_info + key. + +- The name of the username/password authentication mechanism is "PwdAuthenticate" and + it does not require any information to be included under the mechanism_info key. + +The authtoken.settings file contains settings that should be applied to authentication +tokens issued to authenticate to the service. + +The following is an example authtoken.settings file: + + + + 3600 + 10 + CasaIdentityToken + + +Note the following about the sample authtoken.settings file: + +- The settings that you can specify in the authtoken.settings file are: TokenLifetime, + LifetimeShorter, and IdentityTokenType. If one of this tokens is not specified then + its default value is utilized. + +- The TokenLifetime setting specifies the number of seconds for which a token is good + for after being issued. The default value for this setting is 3600 seconds. Note that + a larger value reduces overhead, but it also gives more time for an intruder to + utilize the token if it becomes compromized. + +- The LifetimeShorter setting specifies the number of seconds that should be substracted + from the TokenLifetime when calculating the number of seconds that clients are told + that the tokens are good for. The default value for this setting is 5 seconds. + +- The IdentityTokenType specifies the type of identity tokens that must be embedded in + the authentication tokens with identity information. The default value for this + setting is CasaIdentityToken. + +The identoken.settings file contains settings that should be applied to identity tokens +embedded in authentication tokens. + +The following is an example identoken.settings file: + + + + sn,groupMembership,guid + false + Base64 encoded certificate + + +Note the following about the sample identoken.settings file: + +- The settings that you can specify in the identoken.settings file are: Attributes. + EncryptAttributes, and Certificate. + +- The Attributes setting specifies the identity attributes that must be included + as part of the identity token, The attributes are specified in the form of a coma + delimited list. The default velue for this setting is "sn". + +- The EncryptAtributes setting specifies whether or not the identity information + contained in the identity token should be emcrypted with the services's Public + Certificate. The default value for this setting is "false". Please note that + to enable identity attribute encryption you must not allow the ATS to default to + the file present in its conf folder (Attribute encryption is not yet supported + by the Casa identity token provider). + +- The Certificate setting specifies the certificate that must be utilized to encrypt + identity attribute data. The certificate contains the public key of the targeted + service. The certificate data is Base64 encoded. + +- The identoken.settings file can also contain additional identity token provider + specific settings. + +CONFIGURING AUTHENTICATION MECHANISMS + +Authentication mechanisms available to the AuthTokenSvc are configured by creating +a sub-folder named after the authentication mechanism type under the +conf/auth_mechanisms folder. The authentication mechanism folders must contain a +settings file named mechanism.settings. The mechanism.settings file must contain the +name of the class implementing the mechanism along with path information which +can be utilized by the ATS to load the class. The mechanism.settings file can +also contain mechanism specific settings. + +The following setting is mandatory: + +ClassName - This is the name of the class implementing the authentication mechanism. + +One of the following settings must be included: + +RelativeClassPath - This is a relative path from the web application's root folder +to the folder containing the class implementing the mechanism. + +ClassPath - This is an absolute path to the folder containing the path to the class +implementing the mechanism. + +The following is an example mechanism.settings file for the Krb5Authentication +mechanism: + + + + com.novell.casa.authtoksvc.Krb5Authenticate + WEB-INF/classes + host@authtokenserver.company.com + + +The base AuthTokenSvc package contains two authentication mechanisms, these are +Krb5Authenticate and PwdAuthenticate. The configuration under sampleConf is set up +to allow an AuthTokenSvc to leverage both mechanisms. + +The Krb5Authenticate mechanism requires that the following setting also be included +in its mechanism.settings file: + +ServicePrincipalName - This is the name of the Kerberos Service Principal that the +Authentication Token Service runs as when authenticating other entities. + +CONFIGURING ADDITIONAL IDENTITY TOKEN PROVIDERS + +- TBD - + +SECURITY CONSIDERATIONS + +- TBD - + + + + + + + + + + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/TODO b/CASA-auth-token/java/server/AuthTokenSvc/TODO new file mode 100644 index 00000000..7d10724a --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/TODO @@ -0,0 +1,21 @@ +/*********************************************************************** + * + * TODO for AuthTokenSvc + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for AuthTokenSvc. + +OUTSTANDING ITEMS + +- Switch to a Web Services model where the Client/Server protocol uses SOAP. +- Switch to use WS-Security, WS-Policy, and WS-Conversation for Authentication Tokens and Session Tokens. +- Add code to verify that client/server communications occur over HTTPS. +- Add logging. +- Create plug-in API for Identity Token Providers. +- Integrate into CASA build environment. +- Review Code. +- Change printfs used for debugging into a suitable mechanism. + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/authtoken.settings b/CASA-auth-token/java/server/AuthTokenSvc/authtoken.settings new file mode 100644 index 00000000..75f4b75c --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/authtoken.settings @@ -0,0 +1,4 @@ + + + 3600 + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/identoken.settings b/CASA-auth-token/java/server/AuthTokenSvc/identoken.settings new file mode 100644 index 00000000..ac54afb5 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/identoken.settings @@ -0,0 +1,6 @@ + + + false + sn + + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth.policy b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth.policy new file mode 100644 index 00000000..d688b944 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth.policy @@ -0,0 +1,13 @@ + + + + CorpTree + Krb5Authenticate + host@authtokenserver.company.com + + + CorpTree + PwdAuthenticate + + + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth_mechanisms/Krb5Authenticate/mechanism.settings b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth_mechanisms/Krb5Authenticate/mechanism.settings new file mode 100644 index 00000000..56110b52 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth_mechanisms/Krb5Authenticate/mechanism.settings @@ -0,0 +1,6 @@ + + + com.novell.casa.authtoksvc.Krb5Authenticate + WEB-INF/classes + host@tokenserver.company.novell.com + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth_mechanisms/PwdAuthenticate/mechanism.settings b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth_mechanisms/PwdAuthenticate/mechanism.settings new file mode 100644 index 00000000..2a5f60f0 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/auth_mechanisms/PwdAuthenticate/mechanism.settings @@ -0,0 +1,5 @@ + + + com.novell.casa.authtoksvc.PwdAuthenticate + WEB-INF/classes + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/authtoken.settings b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/authtoken.settings new file mode 100644 index 00000000..75f4b75c --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/authtoken.settings @@ -0,0 +1,4 @@ + + + 3600 + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/auth.policy b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/auth.policy new file mode 100644 index 00000000..0f7de72b --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/auth.policy @@ -0,0 +1,13 @@ + + + + CorpTree + Krb5Authenticate + host@tokenserver.company.novell.com + + + CorpTree + PwdAuthenticate + + + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/authtoken.settings b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/authtoken.settings new file mode 100644 index 00000000..75f4b75c --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/authtoken.settings @@ -0,0 +1,4 @@ + + + 3600 + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/identoken.settings b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/identoken.settings new file mode 100644 index 00000000..b1d40db3 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/enabled_services/appserver.companyname.com/testService/identoken.settings @@ -0,0 +1,6 @@ + + + false + sn,groupMembership + + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/iaRealms.xml b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/iaRealms.xml new file mode 100644 index 00000000..bc49eb2b --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/iaRealms.xml @@ -0,0 +1,25 @@ + + + + ldap://dirserver.companyname.com:389 + + simple + cn=admin,o=companyname + password + + + + + + CorpTree + + + + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/identoken.settings b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/identoken.settings new file mode 100644 index 00000000..ac54afb5 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/identoken.settings @@ -0,0 +1,6 @@ + + + false + sn + + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/svc.settings b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/svc.settings new file mode 100644 index 00000000..c1465cc0 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/sampleConf/svc.settings @@ -0,0 +1,5 @@ + + + /home/jluciani/jakarta-tomcat-5.0.28/webapps/CasaAuthTokenSvc/WEB-INF/conf/iaRealms.xml + 43200 + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/Makefile.am b/CASA-auth-token/java/server/AuthTokenSvc/src/Makefile.am new file mode 100644 index 00000000..00e1ef35 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = com + +DIST_SUBDIRS = com + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/Makefile.am b/CASA-auth-token/java/server/AuthTokenSvc/src/com/Makefile.am new file mode 100644 index 00000000..34a83b0d --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = novell + +DIST_SUBDIRS = novell + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/Makefile.am b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/Makefile.am new file mode 100644 index 00000000..2fb64053 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = casa + +DIST_SUBDIRS = casa + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/Makefile.am b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/Makefile.am new file mode 100644 index 00000000..2ebc7e01 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = authtoksvc + +DIST_SUBDIRS = authtoksvc + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechConfig.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechConfig.java new file mode 100644 index 00000000..6d08dd58 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechConfig.java @@ -0,0 +1,258 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * AuthMechConfig Class. + * + * This class obtains and maintains authentication token configuration. + * + */ +public class AuthMechConfig +{ + // Well known authentication token configuration settings + public final static String ClassName = "ClassName"; + public final static String RelativeClassPath = "RelativeClassPath"; + public final static String ClassPath = "ClassPath"; + + private Map m_mechSettingsMap; + + /* + * Class for handling parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_SETTING_ELEMENT_START = 1; + private final static int AWAITING_SETTING_ELEMENT_DATA = 2; + private final static int AWAITING_SETTING_ELEMENT_END = 3; + private final static int DONE_PARSING = 4; + + private final static String m_rootElementName = "settings"; + + private Map m_keyMap; + private int m_state; + private String m_currentKey; + + /* + * Constructor + */ + public SAXHandler(Map keyMap) + { + super(); + + // Initialize our members + m_keyMap = keyMap; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we are not in an invalid state + if (m_state != DONE_PARSING) + { + System.err.println("AuthMechConfig SAXHandler.endDocument()- Invalid state" + m_state); + throw new SAXException("Invalid state at endDocument"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + } + else + { + System.err.println("AuthMechConfig SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SETTING_ELEMENT_START: + // Keep track of the key name + m_currentKey = qName; + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_DATA; + break; + + default: + System.err.println("AuthMechConfig SAXHandler.startElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at startElement"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_SETTING_ELEMENT_DATA: + case AWAITING_SETTING_ELEMENT_END: + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + break; + + case AWAITING_SETTING_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("AuthMechConfig SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("AuthMechConfig SAXHandler.endElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at endElement"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Consume the data if in the right state + if (m_state == AWAITING_SETTING_ELEMENT_DATA) + { + // Consume the data and add the key to map + m_keyMap.put(m_currentKey, new String(ch, start, length)); + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_END; + } + } + } + + /* + * Constructor which sets default configuration values. + */ + public AuthMechConfig() throws Exception + { + System.err.println("AuthMechConfig()- Default"); + + // Create a map to keep track of the token settings + m_mechSettingsMap = new HashMap(); + } + + /* + * Constructor. + */ + public AuthMechConfig(String mechSettingsFileName) throws Exception + { + System.err.println("AuthMechConfig()-"); + + // Create a map to keep track of the token settings + m_mechSettingsMap = new HashMap(); + + try + { + // Get an input stream to read from the token settings file + File f = new File(mechSettingsFileName); + FileInputStream inStream = new FileInputStream(f); + + // Parse the file + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(m_mechSettingsMap); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + + inStream.close(); + } + catch (SAXException e) + { + System.err.println("AuthMechConfig()- " + mechSettingsFileName + " format error, exception: " + e.toString()); + throw new Exception("AuthMechConfig()- authtoken.settings format error"); + } + catch (SecurityException e) + { + System.err.println("AuthMechConfig()- SecurityException accessing " + mechSettingsFileName + " Exception=" + e.toString()); + throw new Exception("AuthMechConfig()- Not able to access file"); + } + catch (FileNotFoundException e) + { + System.err.println("AuthMechConfig()- File " + mechSettingsFileName + " not found"); + throw new Exception("AuthMechConfig()- File not found"); + } + catch (IOException e) + { + System.err.println("AuthMechConfig()- IOException accessing " + mechSettingsFileName + " Exception=" + e.toString()); + throw new Exception("AuthMechConfig()- Read error"); + } + } + + /* + * Returns the value associated with the specified setting. + */ + public String getSetting(String settingName) throws Exception + { + // Try to find the setting in our map + String value = (String) m_mechSettingsMap.get(settingName); + if (value == null) + { + System.err.println("AuthMechConfig.getSetting()- Did not find setting " + settingName); + } + else + { + System.err.println("AuthMechConfig.getSetting()- Found setting " + settingName); + System.err.println("AuthMechConfig.getSetting()- Setting value = " + value); + } + + return value; + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechanism.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechanism.java new file mode 100644 index 00000000..a03dc277 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechanism.java @@ -0,0 +1,53 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +/* + * AuthMechanism Interface. + * + * This is the interface implemented by Authentication Mechanisms. + * + * Please note that Authentication Machanisms must also implement the + * Serializable interface. + * + */ +public interface AuthMechanism +{ + /* + * Initialize the authentication mechanism. + */ + void init(SvcConfig svcConfig, AuthMechConfig mechConfig) throws Exception; + + /* + * Process authenticate request. If successful, return the Id of the + * authenticated identity. + */ + String invoke(AuthReqMsg authReqMsg) throws Exception; + + /* + * Return the mechanism id. + */ + String getId(); +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthReqMsg.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthReqMsg.java new file mode 100644 index 00000000..c220efd0 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthReqMsg.java @@ -0,0 +1,328 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.InputStream; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + + +/** + * AuthReqMsg Class. + * + * This class deals with the message sent by Casa Client when requesting + * that an entity be authenticated. The format of the message is as + * follows: + * + * + * + * realm value + * mechanism id + * mechanism token data + * + * + */ +public class AuthReqMsg +{ + + protected String m_realm = null; + protected String m_authMechToken = null; + protected String m_authMechanism = null; + + /* + * Class for handling Authentication Request parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_ROOT_ELEMENT_END = 1; + private final static int AWAITING_REALM_ELEMENT_START = 2; + private final static int AWAITING_REALM_ELEMENT_END = 3; + private final static int AWAITING_REALM_DATA = 4; + private final static int AWAITING_MECH_ELEMENT_START = 5; + private final static int AWAITING_MECH_ELEMENT_END = 6; + private final static int AWAITING_MECH_DATA = 7; + private final static int AWAITING_AUTH_MECH_TOKEN_ELEMENT_START = 8; + private final static int AWAITING_AUTH_MECH_TOKEN_ELEMENT_END = 9; + private final static int AWAITING_AUTH_MECH_TOKEN_DATA = 10; + private final static int DONE_PARSING = 11; + + private AuthReqMsg m_authReqMsg; + private int m_state; + + /* + * Constructor + */ + public SAXHandler (AuthReqMsg authReqMsg) + { + super(); + + // Initialize our members + m_authReqMsg = authReqMsg; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we obtained all of the required elements + if (m_state != DONE_PARSING) + { + System.err.println("AuthReqMsg SAXHandler.endDocument()- Missing element"); + throw new SAXException("Missing element"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.authRequestElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_REALM_ELEMENT_START; + } + else + { + System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_REALM_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.realmElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_REALM_DATA; + } + else + { + System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_MECH_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.mechanismElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_MECH_DATA; + } + else + { + System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_AUTH_MECH_TOKEN_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.authMechTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_AUTH_MECH_TOKEN_DATA; + } + else + { + System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("AuthReqMsg SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_ROOT_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.authRequestElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_REALM_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.realmElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_MECH_ELEMENT_START; + } + else + { + System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_MECH_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.mechanismElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_START; + } + else + { + System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_AUTH_MECH_TOKEN_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.authMechTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ROOT_ELEMENT_END; + } + else + { + System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("AuthReqMsg SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_REALM_DATA: + // Consume the data + m_authReqMsg.m_realm = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_REALM_ELEMENT_END; + break; + + case AWAITING_MECH_DATA: + // Consume the data + m_authReqMsg.m_authMechanism = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_MECH_ELEMENT_END; + break; + + case AWAITING_AUTH_MECH_TOKEN_DATA: + // Consume the data + m_authReqMsg.m_authMechToken = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_END; + break; + + default: + // Do nothing + break; + } + } + } + + /* + * Constructor + */ + public AuthReqMsg (InputStream inStream) throws Exception + { + try + { + // Parse the AuthReqMsg + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(this); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + } + catch (SAXException e) + { + System.err.println("AuthReqMsg()- Parse exception: " + e.toString()); + throw new Exception("Protocol error"); + } + } + + /* + * Method to get the authentication realm. + */ + public String getRealm() throws Exception + { + return m_realm; + } + + /* + * Method to get the authentication mechanism token. + */ + public String getAuthMechToken() throws Exception + { + return m_authMechToken; + } + + /* + * Method to get the authentication mechanism id. + */ + public String getMechanismId() throws Exception + { + return m_authMechanism; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthRespMsg.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthRespMsg.java new file mode 100644 index 00000000..6e1bc49f --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthRespMsg.java @@ -0,0 +1,113 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +/** + * AuthRespMsg Class. + * + * This class deals with the message sent to the CASA Client as a + * response to an authentication request. The format of the message is + * as follows when the response includes a session token: + * + * + * + * OK200 + * lifetime valuesession token data + * + * + * The format of the message is as follows when the response does not + * include a session token. + * + * + * + * status descriptionstatus code + * + * + * Plase note that the protocol utilizes the status codes defined + * in the HTTP 1.1 Specification. + * + */ +public class AuthRespMsg +{ + + String m_msg; + + /* + * Constructor for a msg that does not include the session token. + */ + public AuthRespMsg ( + String statusDescription, + String statusCode) throws Exception + { + // Get a StringBuffer to help us with the construction of the message + StringBuffer sb = new StringBuffer(); + + // Start building the message + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + ProtoDefs.authResponseElementName + ">" + "\r\n"); + sb.append("<" + ProtoDefs.statusElementName + ">" + + "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "" + + statusCode + "" + "\r\n"); + sb.append("" + "\r\n"); + + // The message has now been built, save it. + m_msg = sb.toString(); + } + + /* + * Constructor for a msg that includes the session token. + */ + public AuthRespMsg ( + String statusDescription, + String statusCode, + String sessionToken, + String sessionTokenLifetime) throws Exception + { + // Get a StringBuffer to help us with the construction of the message + StringBuffer sb = new StringBuffer(); + + // Start building the message + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + ProtoDefs.authResponseElementName + ">" + "\r\n"); + sb.append("<" + ProtoDefs.statusElementName + ">" + + "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "" + + ProtoDefs.httpOkStatusCode + "" + "\r\n"); + sb.append("<" + ProtoDefs.sessionTokenElementName + ">" + + "<" + ProtoDefs.lifetimeElementName + ">" + sessionTokenLifetime + "" + + sessionToken + "" + "\r\n"); + sb.append("" + "\r\n"); + + // The message has now been built, save it. + m_msg = sb.toString(); + } + + /* + * Returns a string containing the AuthRespMsg. + */ + public String toString() + { + return m_msg; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthToken.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthToken.java new file mode 100644 index 00000000..b081ea8a --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthToken.java @@ -0,0 +1,466 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.ByteArrayInputStream; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + + +/* + * AuthToken Class. + * + * This class constructs authentication tokens that clients can present + * to services for authentication. The format of the authentication token + * is as follows: + * + * + * + * signature value + * lifetime value + * Identity Token typeidentity token data + * + * + */ +public class AuthToken +{ + + private String m_token; + private String m_lifetime; + private String m_lifetimeShorter; + private String m_identityTokenType; + private StringBuffer m_identityToken; + private String m_signature; + + /* + * Class for handling parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_ROOT_ELEMENT_END = 1; + private final static int AWAITING_SIGNATURE_ELEMENT_START = 2; + private final static int AWAITING_SIGNATURE_ELEMENT_END = 3; + private final static int AWAITING_SIGNATURE_DATA = 4; + private final static int AWAITING_LIFETIME_ELEMENT_START = 5; + private final static int AWAITING_LIFETIME_ELEMENT_END = 6; + private final static int AWAITING_LIFETIME_DATA = 7; + private final static int AWAITING_IDENT_TOKEN_ELEMENT_START = 8; + private final static int AWAITING_IDENT_TOKEN_ELEMENT_END = 9; + private final static int AWAITING_IDENT_TOKEN_DATA = 10; + private final static int AWAITING_TYPE_ELEMENT_START = 11; + private final static int AWAITING_TYPE_ELEMENT_END = 12; + private final static int AWAITING_TYPE_DATA = 13; + private final static int DONE_PARSING = 14; + + private AuthToken m_AuthToken; + private int m_state; + + /* + * Constructor + */ + public SAXHandler (AuthToken AuthToken) + { + super(); + + // Initialize our members + m_AuthToken = AuthToken; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we obtained all of the required elements + if (m_state != DONE_PARSING) + { + System.err.println("AuthToken SAXHandler.endDocument()- Missing element"); + throw new SAXException("Missing element"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.authTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SIGNATURE_ELEMENT_START; + } + else + { + System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SIGNATURE_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.signatureElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SIGNATURE_DATA; + } + else + { + System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_LIFETIME_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.lifetimeElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_LIFETIME_DATA; + } + else + { + System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + + break; + + case AWAITING_IDENT_TOKEN_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.identTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_TYPE_ELEMENT_START; + } + else + { + System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_TYPE_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.typeElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_TYPE_DATA; + } + else + { + System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("AuthToken SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.authTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SIGNATURE_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.signatureElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_LIFETIME_ELEMENT_START; + } + else + { + System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_LIFETIME_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.lifetimeElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_IDENT_TOKEN_ELEMENT_START; + } + else + { + System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_TYPE_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.typeElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_IDENT_TOKEN_DATA; + } + else + { + System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_IDENT_TOKEN_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.identTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ROOT_ELEMENT_END; + } + else + { + System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("AuthToken SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_SIGNATURE_DATA: + // Consume the data + m_AuthToken.m_signature = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_SIGNATURE_ELEMENT_END; + break; + + case AWAITING_LIFETIME_DATA: + // Consume the data + m_AuthToken.m_lifetime = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_LIFETIME_ELEMENT_END; + break; + + case AWAITING_TYPE_DATA: + // Consume the data + m_AuthToken.m_identityTokenType = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_TYPE_ELEMENT_END; + break; + + case AWAITING_IDENT_TOKEN_DATA: + case AWAITING_IDENT_TOKEN_ELEMENT_END: + // Consume the data + m_AuthToken.m_identityToken.append(ch, start, length); + + // Advance to the next state + m_state = AWAITING_IDENT_TOKEN_ELEMENT_END; + break; + + default: + // Do nothing + break; + } + } + } + + /* + * Constructor. + */ + public AuthToken(String identityId, + String realm, + String targetService, + String targetHost, + SvcConfig svcConfig, + EnabledSvcsConfig enabledSvcsConfig) throws Exception + { + // Get access to the authentication token configuration for this service + AuthTokenConfig authTokenConfig = enabledSvcsConfig.getAuthTokenConfig(targetHost, targetService); + if (authTokenConfig != null) + { + try + { + // For now lets use the services of the only IdentityToken provider + // that we have. + // + // tbd - Add code to allow for the consumption of tokens + // from different providers. + CasaIdentityToken identityToken = new CasaIdentityToken(enabledSvcsConfig.getIdenTokenConfig(targetHost, targetService)); + identityToken.initialize(identityId, + realm, + targetService, + targetHost, + svcConfig); + + m_identityToken = new StringBuffer(); + m_identityToken.append(identityToken.getEncodedToken()); + m_identityTokenType = identityToken.getProviderType(); + + m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime); + m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter); + + // Generate a signature + // tbd - Over identToken, identToken type, and lifetime data. + m_signature = "tbd"; + + // Get a StringBuffer to help us with the construction of the token + StringBuffer sb = new StringBuffer(); + + // Start building the message + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + ProtoDefs.authTokenElementName + ">" + "\r\n"); + sb.append("<" + ProtoDefs.signatureElementName + ">" + m_signature + "" + "\r\n"); + sb.append("<" + ProtoDefs.lifetimeElementName + ">" + m_lifetime + "" + "\r\n"); + sb.append("<" + ProtoDefs.identTokenElementName + ">" + + "<" + ProtoDefs.typeElementName + ">" + m_identityTokenType + "" + + m_identityToken + "" + "\r\n"); + sb.append("" + "\r\n"); + + // Save the token + m_token = sb.toString(); + } + catch (Exception e) + { + // tbd + System.err.println("AuthToken()- Exception: " + e.toString()); + } + } + else + { + throw new Exception("Error: Missing authentication token config for " + targetService); + } + } + + /* + * Constructor given an authentication token string. The constructor + * validates the token as part of its processing. + */ + public AuthToken(String token) throws Exception + { + // Decode the token string + m_token = Base64Coder.decode(token); + + // Instantiate string buffer for the identity token + m_identityToken = new StringBuffer(); + + // Now parse the token into its elements + try + { + // Parse the AuthToken + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(this); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes()); + InputSource source = new InputSource(inStream); + xr.parse(source); + + // Verify the signature + // tbd + + // Verify that the token has not expired + // tbd + } + catch (SAXException e) + { + System.err.println("AuthToken()- Parse exception: " + e.toString()); + throw new Exception("Protocol error"); + } + } + + /* + * Returns a string containing the Base64 encode token. + */ + public String toString() + { + return Base64Coder.encode(m_token); + } + + /* + * Returns the lifetime of the token. + */ + public String getLifetime() + { + // tbd - Convert to tokenLifetime and lifetimeShorter to ints, substractand then convert result to string + return "60"; + } + + /* + * Returns the identity token. + */ + public String getIdentityToken() + { + return m_identityToken.toString(); + } + + /* + * Returns the identity token type. + */ + public String getIdentityTokenType() + { + return m_identityTokenType; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java new file mode 100644 index 00000000..27d40aa3 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java @@ -0,0 +1,298 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * AuthTokenConfig Class. + * + * This class obtains and maintains authentication token configuration. + * + */ +public class AuthTokenConfig +{ + // Well known authentication token configuration settings + public final static String TokenLifetime = "TokenLifetime"; + public final static String LifetimeShorter = "LifetimeShorter"; + public final static String IdentityTokenType = "IdentityTokenType"; + + // Default configuration values + private String m_defaultTokenLifetimeValue = "3600"; // Seconds + private String m_defaultLifetimeShorterValue = "5"; // Seconds + private String m_defaultIdentityTokenTypeValue = "CasaIdentityToken"; + + private Map m_tokenSettingsMap; + + /* + * Class for handling parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_SETTING_ELEMENT_START = 1; + private final static int AWAITING_SETTING_ELEMENT_DATA = 2; + private final static int AWAITING_SETTING_ELEMENT_END = 3; + private final static int DONE_PARSING = 4; + + private final static String m_rootElementName = "settings"; + + private Map m_keyMap; + private int m_state; + private String m_currentKey; + + /* + * Constructor + */ + public SAXHandler(Map keyMap) + { + super(); + + // Initialize our members + m_keyMap = keyMap; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we are not in an invalid state + if (m_state != DONE_PARSING) + { + System.err.println("AuthTokenConfig SAXHandler.endDocument()- Invalid state" + m_state); + throw new SAXException("Invalid state at endDocument"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + } + else + { + System.err.println("AuthTokenConfig SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SETTING_ELEMENT_START: + // Keep track of the key name + m_currentKey = qName; + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_DATA; + break; + + default: + System.err.println("AuthTokenConfig SAXHandler.startElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at startElement"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_SETTING_ELEMENT_DATA: + case AWAITING_SETTING_ELEMENT_END: + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + break; + + case AWAITING_SETTING_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("AuthTokenConfig SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("AuthTokenConfig SAXHandler.endElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at endElement"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Consume the data if in the right state + if (m_state == AWAITING_SETTING_ELEMENT_DATA) + { + // Consume the data and add the key to map + m_keyMap.put(m_currentKey, new String(ch, start, length)); + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_END; + } + } + } + + /* + * Constructor which sets default configuration values. + */ + public AuthTokenConfig() throws Exception + { + System.err.println("AuthTokenConfig()- Default"); + + // Create a map to keep track of the token settings + m_tokenSettingsMap = new HashMap(); + + // Set the default settings in our map + m_tokenSettingsMap.put(TokenLifetime, m_defaultTokenLifetimeValue); + m_tokenSettingsMap.put(LifetimeShorter, m_defaultLifetimeShorterValue); + m_tokenSettingsMap.put(IdentityTokenType, m_defaultIdentityTokenTypeValue); + } + + /* + * Constructor. + */ + public AuthTokenConfig(String authTokenSettingsFileName) throws Exception + { + System.err.println("AuthTokenConfig()-"); + + // Create a map to keep track of the token settings + m_tokenSettingsMap = new HashMap(); + + try + { + // Get an input stream to read from the token settings file + File f = new File(authTokenSettingsFileName); + FileInputStream inStream = new FileInputStream(f); + + // Parse the file + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(m_tokenSettingsMap); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + + inStream.close(); + } + catch (SAXException e) + { + System.err.println("AuthTokenConfig()- " + authTokenSettingsFileName + " format error, exception: " + e.toString()); + throw new Exception("AuthTokenConfig()- authtoken.settings format error"); + } + catch (SecurityException e) + { + System.err.println("AuthTokenConfig()- SecurityException accessing " + authTokenSettingsFileName + " Exception=" + e.toString()); + throw new Exception("AuthTokenConfig()- Not able to access file"); + } + catch (FileNotFoundException e) + { + System.err.println("AuthTokenConfig()- File " + authTokenSettingsFileName + " not found"); + throw new Exception("AuthTokenConfig()- File not found"); + } + catch (IOException e) + { + System.err.println("AuthTokenConfig()- IOException accessing " + authTokenSettingsFileName + " Exception=" + e.toString()); + throw new Exception("AuthTokenConfig()- Read error"); + } + } + + /* + * Returns the value associated with the specified setting. + */ + public String getSetting(String settingName) throws Exception + { + // Try to find the setting in our map + String value = (String) m_tokenSettingsMap.get(settingName); + if (value == null) + { + System.err.println("AuthTokenConfig.getSetting()- Did not find setting " + settingName); + + // The setting is not in our map, check if it is one to + // which we have defaults. + if (settingName.equals(TokenLifetime) == true) + { + value = m_defaultTokenLifetimeValue; + System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_tokenSettingsMap.put(TokenLifetime, m_defaultTokenLifetimeValue); + } + else if (settingName.equals(LifetimeShorter) == true) + { + value = m_defaultLifetimeShorterValue; + System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_tokenSettingsMap.put(LifetimeShorter, m_defaultLifetimeShorterValue); + } + else if (settingName.equals(IdentityTokenType) == true) + { + value = m_defaultLifetimeShorterValue; + System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_tokenSettingsMap.put(IdentityTokenType, m_defaultIdentityTokenTypeValue); + } + } + else + { + System.err.println("AuthTokenConfig.getSetting()- Found setting " + settingName); + System.err.println("AuthTokenConfig.getSetting()- Setting value = " + value); + + // Do some sanity checking + // tbd - Make sure that the token lifetime values are greater than the LifetimeShorter + } + + return value; + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Authenticate.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Authenticate.java new file mode 100644 index 00000000..fb4a24da --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Authenticate.java @@ -0,0 +1,341 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.util.*; +import java.io.*; + +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; + +import java.net.URL; +import java.net.MalformedURLException; +import java.net.URLClassLoader; + +/** + * Authenticate Class. + * + * This class processes authentication requests. + * + */ +public class Authenticate implements RpcMethod +{ + private static final String m_mechanismSettingsFileName = "mechanism.settings"; + + private Map m_authMechanismMap; + + private SvcConfig m_svcConfig; + private EnabledSvcsConfig m_enabledSvcsConfig; + + /* + * Constructor + */ + public Authenticate() throws Exception + { + // Create a map to keep track of the authentication mechanisms + m_authMechanismMap = new HashMap(); + } + + /* + * Initialize the Rpc method. + */ + public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception + { + m_svcConfig = svcConfig; + m_enabledSvcsConfig = enabledSvcsConfig; + + // Now go through the configured authentication mechanisms, as we do so, instantiate + // the mechanisms and place them in our map. Note that the mechanisms config folder + // contains folders for each installed authentication mechanism. The name of these + // folders usually match the name of the Authentication mechanisms. + String svcConfigPath = svcConfig.getSetting(SvcConfig.ConfigFolderPath); + File mechanismsConfigFolder = new File(svcConfigPath, "auth_mechanisms"); + try + { + String[] mechanismsConfigFolderObjs = mechanismsConfigFolder.list(); + if (mechanismsConfigFolderObjs != null) + { + for (int i = 0; i < mechanismsConfigFolderObjs.length; i++) + { + // Check if we are dealing with a file or a folder + File mechanismFolder = new File(mechanismsConfigFolder, mechanismsConfigFolderObjs[i]); + try + { + if (mechanismFolder.isDirectory() == true) + { + System.err.println("Authenticate.init()- Mechanism folder " + mechanismFolder + " is directory"); + + // Try to obtain the mechanism settings + try + { + AuthMechConfig mechConfig = new AuthMechConfig(mechanismFolder + File.separator + m_mechanismSettingsFileName); + + // Mechanism settings obtained, now instantiate it and place it in our map. + // + String mechClassName = mechConfig.getSetting(AuthMechConfig.ClassName); + if (mechClassName != null) + { + // We now know the name of the class implementing the mechanism, now lets + // get the relative path to the class file. Note that the path is relative + // to the root folder of our application. + String relativePath = mechConfig.getSetting(AuthMechConfig.RelativeClassPath); + if (relativePath != null) + { + // Create a file object to the folder containing the class file. Note that we need to + // ultimately instantiate objects from a class loaded by the same class loader that + // loads the AuthMechanism class to avoid ClassCastExceptions. + File mechClassPathFile = new File(svcConfig.getSetting(SvcConfig.AppRootPath) + relativePath); + System.err.println("Authenticate.init()- Mechanism path = " + mechClassPathFile); + try + { + URL methClassPathUrl = mechClassPathFile.toURL(); + URL[] urls = new URL[]{methClassPathUrl}; + + // Create a class loader for the folder + ClassLoader customClassLoader = new URLClassLoader(urls); + + // Load the mech class using our custom loader + Class mechClass = customClassLoader.loadClass(mechClassName); + FileOutputStream fos = new FileOutputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(mechClass); + oos.close(); + fos.close(); + FileInputStream fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); + ObjectInputStream ois = new ObjectInputStream(fis); + mechClass = (Class) ois.readObject(); + ois.close(); + fis.close(); + + // Now reload the class using the class loader for our AuthMechanism class + AuthMechanism mechanism = (AuthMechanism) mechClass.newInstance(); + mechanism.init(svcConfig, mechConfig); + m_authMechanismMap.put(mechanism.getId(), mechanism); + } + catch (MalformedURLException e) + { + System.err.println("Authenticate.init()- MalformedURLException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + catch (ClassNotFoundException e) + { + System.err.println("Authenticate.init()- ClassNotFoundException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + catch (InstantiationException e) + { + System.err.println("Authenticate.init()- InstantiationException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + catch (IllegalAccessException e) + { + System.err.println("Authenticate.init()- IllegalAccessException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + } + else + { + // A relative path was not configured, check if instead a full path was configured. + String classPath = mechConfig.getSetting(AuthMechConfig.ClassPath); + if (classPath != null) + { + // Create a file object to the folder containing the class file. Note that we need to + // ultimately instantiate objects from a class loaded by the same class loader that + // loads the AuthMechanism class to avoid ClassCastExceptions. + File mechClassPathFile = new File(classPath); + System.err.println("Authenticate.init()- Mechanism path = " + mechClassPathFile); + try + { + URL methClassPathUrl = mechClassPathFile.toURL(); + URL[] urls = new URL[]{methClassPathUrl}; + + // Create a class loader for the folder + ClassLoader customClassLoader = new URLClassLoader(urls); + + // Load the mech class using our custom loader + Class mechClass = customClassLoader.loadClass(mechClassName); + FileOutputStream fos = new FileOutputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(mechClass); + oos.close(); + fos.close(); + FileInputStream fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); + ObjectInputStream ois = new ObjectInputStream(fis); + mechClass = (Class) ois.readObject(); + ois.close(); + fis.close(); + + // Now reload the class using the class loader for our AuthMechanism class + AuthMechanism mechanism = (AuthMechanism) mechClass.newInstance(); + mechanism.init(svcConfig, mechConfig); + m_authMechanismMap.put(mechanism.getId(), mechanism); + } + catch (MalformedURLException e) + { + System.err.println("Authenticate.init()- MalformedURLException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + catch (ClassNotFoundException e) + { + System.err.println("Authenticate.init()- ClassNotFoundException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + catch (InstantiationException e) + { + System.err.println("Authenticate.init()- InstantiationException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + catch (IllegalAccessException e) + { + System.err.println("Authenticate.init()- IllegalAccessException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + } + else + { + System.err.println("Authenticate.init()- No configuration to find class path to load " + mechanismFolder + File.separator + m_mechanismSettingsFileName); + } + } + } + else + { + System.err.println("Authenticate.init()- No configured mechanism class name for " + mechanismFolder + File.separator + m_mechanismSettingsFileName); + } + } + catch (SecurityException e) + { + System.err.println("Authenticate.init()- SecurityException accessing " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + catch (FileNotFoundException e) + { + System.err.println("Authenticate.init()- No authentication policy file for " + mechanismFolder); + } + catch (IOException e) + { + System.err.println("Authenticate.init()- IOException reading " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + catch (Exception e) + { + System.err.println("Authenticate.init()- Exception instantiating mechConfig or mechanism " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString()); + } + } + } + catch (SecurityException e) + { + System.err.println("Authenticate.init()- SecurityException accessing " + mechanismFolder + " Exception=" + e.toString()); + } + } + } + else + { + System.err.println("Authenticate.init()- Unable to obtain mechanisms folder " + mechanismsConfigFolder + " objects"); + } + } + catch (SecurityException e) + { + System.err.println("Authenticate.init()- SecurityException accessing " + mechanismsConfigFolder + " Exception=" + e.toString()); + } + } + + /* + * Process Rpc. + */ + public void invoke(InputStream inStream, PrintWriter out) throws IOException + { + try + { + System.err.println("Authenticate.invoke()"); + + // Parse the AuthReqMsg sent from the client + AuthReqMsg authReqMsg = new AuthReqMsg(inStream); + + // Get the necessary authentication mechanism + AuthMechanism authMechanism = (AuthMechanism) m_authMechanismMap.get(authReqMsg.getMechanismId()); + if (authMechanism != null) + { + // Invoke the mechanism to authenticate the entity + String identId = authMechanism.invoke(authReqMsg); + + // Create response based on the identity resolution results + if (identId != null && identId.length() != 0) + { + System.err.println("Authenticate.invoke()- identId resolved, " + identId); + + // An identity was resolved, get a SessionToken for it. + SessionToken sessionToken = new SessionToken(identId, + authReqMsg.getRealm(), + m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)); + + // Write out the response + AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpOkStatusMsg, + ProtoDefs.httpOkStatusCode, + sessionToken.toString(), + m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)); + // tbd - Convert to ints, perform calculation, and then convert result to string + //m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime) + //- m_svcConfig.getSetting(SvcConfig.LifetimeShorter)); + out.println(authRespMsg.toString()); + } + else + { + System.err.println("Authenticate.invoke()- identId not resolved"); + + // Write out the response + AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpUnauthorizedStatusMsg, + ProtoDefs.httpUnauthorizedStatusCode); + out.println(authRespMsg.toString()); + } + } + else + { + System.err.println("Authenticate.invoke()- Unsupported mechanism " + authReqMsg.getMechanismId()); + + // Write out the response + AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpNotFoundStatusMsg, + ProtoDefs.httpNotFoundStatusCode); + out.println(authRespMsg.toString()); + } + } + catch (Exception e) + { + System.err.println("Authenticate.invoke()- Exception: " + e.toString()); + + // Write out the response + try + { + AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpServerErrorStatusMsg, + ProtoDefs.httpServerErrorStatusCode); + out.println(authRespMsg.toString()); + } + catch (Exception e2) + { + System.err.println("Authenticate.invoke()- Exception trying to construct response msg: " + e2.toString()); + } + } + } + + /* + * Return the method id. + */ + public String getId() + { + return "Authenticate"; + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Base64Coder.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Base64Coder.java new file mode 100644 index 00000000..5584b692 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Base64Coder.java @@ -0,0 +1,121 @@ +/************************************************************************** +* +* A Base64 Encoder/Decoder. +* +* This class is used to encode and decode data in Base64 format +* as described in RFC 1521. +* +*

+* Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.
+* License: This is "Open Source" software and released under the GNU/LGPL license. +* It is provided "as is" without warranty of any kind. Please contact the author for other licensing arrangements.
+* Home page: www.source-code.biz
+* +*

+* Version history:
+* 2003-07-22 Christian d'Heureuse (chdh): Module created.
+* 2005-08-11 chdh: Lincense changed from GPL to LGPL. +* +**************************************************************************/ + +package com.novell.casa.authtoksvc; + +public class Base64Coder { + +// Mapping table from 6-bit nibbles to Base64 characters. +private static char[] map1 = new char[64]; + static { + int i=0; + for (char c='A'; c<='Z'; c++) map1[i++] = c; + for (char c='a'; c<='z'; c++) map1[i++] = c; + for (char c='0'; c<='9'; c++) map1[i++] = c; + map1[i++] = '+'; map1[i++] = '/'; } + +// Mapping table from Base64 characters to 6-bit nibbles. +private static byte[] map2 = new byte[128]; + static { + for (int i=0; i>> 2; + int o1 = ((i0 & 3) << 4) | (i1 >>> 4); + int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); + int o3 = i2 & 0x3F; + out[op++] = map1[o0]; + out[op++] = map1[o1]; + out[op] = op < oDataLen ? map1[o2] : '='; op++; + out[op] = op < oDataLen ? map1[o3] : '='; op++; } + return out; } + +/** +* Decodes a Base64 string. +* @param s a Base64 String to be decoded. +* @return A String containing the decoded data. +* @throws IllegalArgumentException if the input is not valid Base64 encoded data. +*/ +public static String decode (String s) { + return new String(decode(s.toCharArray())); } + +/** +* Decodes Base64 data. +* No blanks or line breaks are allowed within the Base64 encoded data. +* @param in a character array containing the Base64 encoded data. +* @return An array containing the decoded data bytes. +* @throws IllegalArgumentException if the input is not valid Base64 encoded data. +*/ +public static byte[] decode (char[] in) { + int iLen = in.length; + if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); + while (iLen > 0 && in[iLen-1] == '=') iLen--; + int oLen = (iLen*3) / 4; + byte[] out = new byte[oLen]; + int ip = 0; + int op = 0; + while (ip < iLen) { + int i0 = in[ip++]; + int i1 = in[ip++]; + int i2 = ip < iLen ? in[ip++] : 'A'; + int i3 = ip < iLen ? in[ip++] : 'A'; + if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) + throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); + int b0 = map2[i0]; + int b1 = map2[i1]; + int b2 = map2[i2]; + int b3 = map2[i3]; + if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) + throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); + int o0 = ( b0 <<2) | (b1>>>4); + int o1 = ((b1 & 0xf)<<4) | (b2>>>2); + int o2 = ((b2 & 3)<<6) | b3; + out[op++] = (byte)o0; + if (op + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.ByteArrayInputStream; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Set; + +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +import org.bandit.ia.IAContext; + +/* + * CasaIdentityToken Class. + * + * This class constructs Casa Identity tokens. + * + * A Casa Identity Token is a simple XML Document + * with information about an identity in the form + * of: + * + * + * + * identity id + * identity data source name + * identity data source url + * target service name + * target host name + * + * attribute value + * attribute2 value + * ... + * + * + * + * + * attribute/values pairs. The attribute names + * being the XML elements of the documents. + * + */ +public class CasaIdentityToken implements IdentityToken +{ + /* + * XML Element Name Constants for the documents exchanged between the + * Casa Client and the Casa Server. + */ + private final static String casaIdentTokElementName = "casa_ident_tok"; + private final static String idElementName = "id"; + private final static String sourceNameElementName = "source_name"; + private final static String sourceUrlElementName = "source_url"; + private final static String targetServiceElementName = "target_service"; + private final static String targetHostElementName = "target_host"; + private final static String attributesElementName = "attributes"; + + private IdenTokenConfig m_idenTokenConfig; + + private String m_identityId = null; + private String m_sourceName = null; + private String m_sourceUrl = null; + private String m_service = null; + private String m_host = null; + private String m_token = null; + private javax.naming.directory.Attributes m_attributes = null; + + /* + * Class for handling Authentication Request parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_ROOT_ELEMENT_END = 1; + private final static int AWAITING_ID_ELEMENT_START = 2; + private final static int AWAITING_ID_ELEMENT_END = 3; + private final static int AWAITING_ID_DATA = 4; + private final static int AWAITING_SOURCE_NAME_ELEMENT_START = 5; + private final static int AWAITING_SOURCE_NAME_ELEMENT_END = 6; + private final static int AWAITING_SOURCE_NAME_DATA = 7; + private final static int AWAITING_SOURCE_URL_ELEMENT_START = 8; + private final static int AWAITING_SOURCE_URL_ELEMENT_END = 9; + private final static int AWAITING_SOURCE_URL_DATA = 10; + private final static int AWAITING_TARGET_SERVICE_ELEMENT_START = 11; + private final static int AWAITING_TARGET_SERVICE_ELEMENT_END = 12; + private final static int AWAITING_TARGET_SERVICE_DATA = 13; + private final static int AWAITING_TARGET_HOST_ELEMENT_START = 14; + private final static int AWAITING_TARGET_HOST_ELEMENT_END = 15; + private final static int AWAITING_TARGET_HOST_DATA = 16; + private final static int AWAITING_ATTRIBUTES_ELEMENT_START = 17; + private final static int AWAITING_ATTRIBUTE_START = 18; + private final static int AWAITING_ATTRIBUTE_END = 19; + private final static int AWAITING_ATTRIBUTE_DATA = 20; + private final static int AWAITING_BINARY_ATTRIBUTE_DATA = 21; + private final static int DONE_PARSING = 22; + + private CasaIdentityToken m_casaIdentToken; + private int m_state; + private String m_currAttribute; + private boolean m_encryptedAttrs; + + /* + * Constructor + */ + public SAXHandler (CasaIdentityToken casaIdentityToken) + { + super(); + + // Initialize our members + m_casaIdentToken = casaIdentityToken; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we obtained all of the required elements + if (m_state != DONE_PARSING) + { + System.err.println("CasaIdentityToken SAXHandler.endDocument()- Missing element"); + throw new SAXException("Missing element"); + } + } + + /* + * + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (casaIdentTokElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ID_ELEMENT_START; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_ID_ELEMENT_START: + // Verify that we are processing the expected tag + if (idElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ID_DATA; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SOURCE_NAME_ELEMENT_START: + // Verify that we are processing the expected tag + if (sourceNameElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SOURCE_NAME_DATA; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + + break; + + case AWAITING_SOURCE_URL_ELEMENT_START: + // Verify that we are processing the expected tag + if (sourceUrlElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SOURCE_URL_DATA; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_TARGET_SERVICE_ELEMENT_START: + // Verify that we are processing the expected tag + if (targetServiceElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_TARGET_SERVICE_DATA; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_TARGET_HOST_ELEMENT_START: + // Verify that we are processing the expected tag + if (targetHostElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_TARGET_HOST_DATA; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_ATTRIBUTES_ELEMENT_START: + // Verify that we are processing the expected tag + if (attributesElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ATTRIBUTE_START; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_ATTRIBUTE_START: + // Save the element name as the current attribute + m_currAttribute = qName; + + // Advance to the next state based on the attribute type + String attrType = atts.getValue("type"); + if (attrType != null && attrType.equals("binary")) + { + // We are dealing with a binary attribute. We are going to + // assume that binary attributes are always base64 encoded. + m_state = AWAITING_BINARY_ATTRIBUTE_DATA; + } + else + { + // Assume we are dealing with an attribute of type string + m_state = AWAITING_ATTRIBUTE_DATA; + } + break; + + default: + System.err.println("CasaIdentityToken SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_END: + // Verify that we are processing the expected tag + if (casaIdentTokElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_ID_ELEMENT_END: + // Verify that we are processing the expected tag + if (idElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SOURCE_NAME_ELEMENT_START; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SOURCE_NAME_ELEMENT_END: + // Verify that we are processing the expected tag + if (sourceNameElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SOURCE_URL_ELEMENT_START; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SOURCE_URL_ELEMENT_END: + // Verify that we are processing the expected tag + if (sourceUrlElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_TARGET_SERVICE_ELEMENT_START; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_TARGET_SERVICE_ELEMENT_END: + // Verify that we are processing the expected tag + if (targetServiceElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_TARGET_HOST_ELEMENT_START; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_TARGET_HOST_ELEMENT_END: + // Verify that we are processing the expected tag + if (targetHostElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ATTRIBUTES_ELEMENT_START; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_ATTRIBUTE_END: + // Advance to the next state + m_state = AWAITING_ATTRIBUTE_START; + break; + + case AWAITING_ATTRIBUTE_START: + // Verify that we are processing the expected tag + if (attributesElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ROOT_ELEMENT_END; + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("CasaIdentityToken SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ID_DATA: + // Consume the data + m_casaIdentToken.m_identityId = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_ID_ELEMENT_END; + break; + + case AWAITING_SOURCE_NAME_DATA: + // Consume the data + m_casaIdentToken.m_sourceName = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_SOURCE_NAME_ELEMENT_END; + break; + + case AWAITING_SOURCE_URL_DATA: + // Consume the data + m_casaIdentToken.m_sourceUrl = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_SOURCE_URL_ELEMENT_END; + break; + + case AWAITING_TARGET_SERVICE_DATA: + // Consume the data + m_casaIdentToken.m_service = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_TARGET_SERVICE_ELEMENT_END; + break; + + case AWAITING_TARGET_HOST_DATA: + // Consume the data + m_casaIdentToken.m_host = new String(ch, start, length); + + // At this point we now have the target service and host names, + // check if our configuration says that the attributes have been + // encrypted. + // tbd - Need to come up with a solution for obtaining configuration + // information when instanstiated using a stream. May be the token should + // carry an indication that the attributes are encrypted. + m_encryptedAttrs = false; + + // Advance to the next state + m_state = AWAITING_TARGET_HOST_ELEMENT_END; + break; + + case AWAITING_ATTRIBUTE_DATA: + // Consume the data + // + // Decrypt the attribute data if necessary + if (m_encryptedAttrs) + { + // tbd - Decrypt the attribute key and value with the private key of the service + // using the configured mechanism. + } + else + { + m_casaIdentToken.m_attributes.put(m_currAttribute, new String(ch, start, length)); + } + + // Advance to the next state + m_state = AWAITING_ATTRIBUTE_END; + break; + + case AWAITING_BINARY_ATTRIBUTE_DATA: + // Consume the data + // + // Decrypt the attribute data if necessary + if (m_encryptedAttrs) + { + // tbd - Decrypt the attribute key and value with the private key of the service + // using the configured mechanism. + } + else + { + // The data is base64 encoded + char[] encodedChars = new char[length]; + System.arraycopy(ch, start, encodedChars, 0, length); + m_casaIdentToken.m_attributes.put(m_currAttribute, Base64Coder.decode(encodedChars)); + } + + // Advance to the next state + m_state = AWAITING_ATTRIBUTE_END; + break; + + default: + // Do nothing + break; + } + } + } + + /* + * Constructor. + */ + public CasaIdentityToken (IdenTokenConfig idenTokenConfig) + { + // Initialize our members + m_token = null; + m_attributes = new javax.naming.directory.BasicAttributes(); + m_idenTokenConfig = idenTokenConfig; + } + + /* + * Constructor. + */ + public CasaIdentityToken () + { + // Initialize our members + m_token = null; + m_attributes = new javax.naming.directory.BasicAttributes(); + m_idenTokenConfig = null; + } + + /* + * Initialize with parameters. + */ + public void initialize (String identityId, + String sourceName, + String targetService, + String targetHost, + SvcConfig svcConfig) throws Exception + { + // Save input parameters + m_identityId = identityId; + m_sourceName = sourceName; + m_sourceUrl = "ldap://myldaphost.novell.com:389"; // tbd - Obtain from Identity Abstraction layer + m_service = targetService; + m_host = targetHost; + + try + { + // Open a directory context and use it to read the identity attributes. + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory"); + env.put(IAContext.IA_REALM_CONFIG_LOCATION, svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile)); + env.put(IAContext.IA_REALM_SELECTOR, sourceName); + + DirContext ctx = new InitialDirContext(env); + + // Setup a string buffer for building the IdentityToken, notice for now + // we are not going to wrap the identity token. + StringBuffer sb = new StringBuffer(); + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + casaIdentTokElementName + ">" + "\r\n"); + sb.append("<" + idElementName + ">" + identityId + "\r\n"); + sb.append("<" + sourceNameElementName + ">" + sourceName + "\r\n"); + sb.append("<" + sourceUrlElementName + ">" + m_sourceUrl + "\r\n"); + sb.append("<" + targetServiceElementName + ">" + m_service + "\r\n"); + sb.append("<" + targetHostElementName + ">" + m_host + "\r\n"); + sb.append("<" + attributesElementName + ">" + "\r\n"); + + // Get the necessary attributes of the specified services in the identity token + String[] attributesNeeded = m_idenTokenConfig.getAttributes(); + boolean encryptAttributes = "true".equals(m_idenTokenConfig.getSetting(IdenTokenConfig.EncryptAttributes)); + Attributes attrs = ctx.getAttributes(identityId, attributesNeeded); + + // Now append the attributes to the token + for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();) + { + javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) ae.next(); + + NamingEnumeration enumeration = attr.getAll(); + while (enumeration.hasMore()) + { + Object attrValue = enumeration.next(); + m_attributes.put(attr.getID(), attrValue); + System.err.println("CasaIdentityToken.initialize()- Including attribute " + attr.getID()); + + // Encrypt the attribute if necessary + if (encryptAttributes == true) + { + // tbd - Encrypt the attributes using the services public key, let the mechanism + // be configurable. The service's certificate should be Base64 encoded as a setting + // of the identoken.settings file. + } + else + { + // Proceed based on the attribute value type + if (attrValue instanceof byte[]) + { + // The attribute value is of type byte[], we need to encode it. + sb.append("<" + attr.getID() + " type=\"binary\" encoding=\"base64\">" + new String(Base64Coder.encode((byte[]) attrValue)) + "" + "\r\n"); + System.err.println("Attribute " + attr.getID() + "included as " + new String(Base64Coder.encode((byte[]) attrValue))); + } + else + { + // Assume the attribute value is of type String + sb.append("<" + attr.getID() + ">" + (String) attrValue + "" + "\r\n"); + } + } + } + } + sb.append("" + "\r\n"); + sb.append("" + "\r\n"); + + m_token = sb.toString(); + } + catch (NamingException e) + { + // tbd - Log the event??? + System.err.println("CasaIdentityToken.initialize()- Exception: " + e.getExplanation()); + } + catch (Exception e) + { + // tbd + System.err.println("CasaIdentityToken.initialize()- Exception: " + e.toString()); + } + } + + /* + * Initialize the token object with an ecoded token string. + */ + public void initialize (String encodedToken) throws Exception + { + // Save copy of the token + m_token = Base64Coder.decode(encodedToken); + + // Now parse the token into its elements + try + { + // Parse the AuthReqMsg + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(this); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + + ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes()); + InputSource source = new InputSource(inStream); + xr.parse(source); + } + catch (SAXException e) + { + // tbd - Log this. + System.err.println("CasaIdentityToken()- Parse exception: " + e.toString()); + throw new Exception("Token error"); + } + } + + /* + * Returns encoded token string. + * + * IMPORTANT: The token string can not contain the substring "]]>" + * within it. + */ + public String getEncodedToken () throws Exception + { + if (m_token != null) + { + return Base64Coder.encode(m_token); + } + else + { + System.err.println("CasaIdentityToken.toString()- Not initialized"); + throw new Exception("Not initialized"); + } + } + + /* + * Returns a string containing our type of identity token provider. + */ + public String getProviderType () throws Exception + { + // tbd - Change to a GUID + return "CasaIdentityToken"; + } + + /* + * Returns a string containing the identity id. + */ + public String getIdentityId () throws Exception + { + if (m_identityId != null) + return m_identityId; + else + { + System.err.println("CasaIdentityToken.getIdentityId()- Not initialized"); + throw new Exception("Not initialized"); + } + } + + /* + * Returns a string containing the name associated with the + * identity source. + */ + public String getSourceName () throws Exception + { + if (m_sourceName != null) + return m_sourceName; + else + { + System.err.println("CasaIdentityToken.getSourceName()- Not initialized"); + throw new Exception("Not initialized"); + } + } + + /* + * Returns a string containing the url associated with the + * identity source. + */ + public String getSourceUrl () throws Exception + { + if (m_sourceUrl != null) + return m_sourceUrl; + else + { + System.err.println("CasaIdentityToken.getSourceUrl()- Not initialized"); + throw new Exception("Not initialized"); + } + } + + /* + * Returns a string containing the name of the targeted service. + */ + public String getTargetService () throws Exception + { + if (m_service != null) + return m_service; + else + { + System.err.println("CasaIdentityToken.getTargetService()- Not initialized"); + throw new Exception("Not initialized"); + } + } + + /* + * Returns a string containig the name of the host where the + * targeted service resides. + */ + public String getTargetHost () throws Exception + { + if (m_host != null) + return m_host; + else + { + System.err.println("CasaIdentityToken.getTargetHost()- Not initialized"); + throw new Exception("Not initialized"); + } + } + + /* + * Returns the attributes of the identity. + */ + public javax.naming.directory.Attributes getAttributes () throws Exception + { + if (m_attributes != null) + return m_attributes; + else + { + System.err.println("CasaIdentityToken.getIdentityAttributes()- Not initialized"); + throw new Exception("Not initialized"); + } + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java new file mode 100644 index 00000000..59301e54 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java @@ -0,0 +1,388 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +/** + * EnabledSvcsConfig Class. + * + * This class obtains and maintains configuration and policy information about + * the services enabled to use Authentication Tokens. + * + */ +public class EnabledSvcsConfig +{ + private static final String m_authPolicyFileName = "auth.policy"; + private static final String m_authTokenSettingsFileName = "authtoken.settings"; + private static final String m_idenTokenSettingsFileName = "identoken.settings"; + + private Map m_hostsMap; + + /** + * SvcConfigEntry Class. + * + * This class is used to maintain the configuration and policy associated with an + * enabled service. + * + */ + private class SvcConfigEntry + { + protected byte[] m_authPolicyFileData; + protected AuthTokenConfig m_authTokenConfig; + protected IdenTokenConfig m_idenTokenConfig; + + /* + * Constructor. + */ + public SvcConfigEntry(byte[] authPolicyFileData, + AuthTokenConfig authTokenConfig, + IdenTokenConfig idenTokenConfig) + { + m_authPolicyFileData = authPolicyFileData; + m_authTokenConfig = authTokenConfig; + m_idenTokenConfig = idenTokenConfig; + } + } + + /* + * Constructor. + */ + public EnabledSvcsConfig(String svcConfigPath) throws Exception + { + System.err.println("EnabledSvcsConfig()-"); + System.err.println("EnabledSvcsConfig()- SvcConfigPath = " + svcConfigPath); + + // Initialize the default auth policy, authtoken, and identtoken configs. + byte[] defaultAuthPolicyData = null; + AuthTokenConfig defaultAuthTokenConfig = null; + IdenTokenConfig defaultIdenTokenConfig = null; + + // Create a map to keep track of the enabled services and their configuration + // for each configured host. + m_hostsMap = new HashMap(); + + // Get access to the configuration folder for the service + File configFolder = new File(svcConfigPath); + try + { + // Try to obtain the default authentication policy + try + { + File f = new File(configFolder, m_authPolicyFileName); + defaultAuthPolicyData = new byte[(int) f.length()]; + FileInputStream inStream = new FileInputStream(f); + int bytesRead = inStream.read(defaultAuthPolicyData); + inStream.close(); + if (bytesRead != defaultAuthPolicyData.length) + { + System.err.println("EnabledSvcsConfig()- Error reading default policy file"); + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + configFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString()); + } + catch (FileNotFoundException e) + { + System.err.println("EnabledSvcsConfig()- File " + configFolder + File.separator + m_authPolicyFileName + " not found"); + } + catch (IOException e) + { + System.err.println("EnabledSvcsConfig()- IOException reading " + configFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString()); + } + + // Try to obtain the default authentication token settings + try + { + defaultAuthTokenConfig = new AuthTokenConfig(configFolder + File.separator + m_authTokenSettingsFileName); + } + catch (Exception e) + { + // Not able to create authentication token configuration using the default + // file. Create one using default parameters. + defaultAuthTokenConfig = new AuthTokenConfig(); + } + + // Try to obtain the default identity token settings + try + { + defaultIdenTokenConfig = new IdenTokenConfig(configFolder + File.separator + m_idenTokenSettingsFileName); + } + catch (Exception e) + { + // Not able to create identity token configuration using the default + // file. Create one using default parameters. + defaultIdenTokenConfig = new IdenTokenConfig(); + } + + // Now go through the configured hosts. Note that the services config folder + // contains folders for each host for which there are enabled services. The folders + // in the services config folder must match the DNS name of the hosts where + // the enabled services reside. + File servicesConfigFolder = new File(svcConfigPath, "enabled_services"); + try + { + String[] servicesConfigFolderObjs = servicesConfigFolder.list(); + if (servicesConfigFolderObjs != null) + { + for (int i = 0; i < servicesConfigFolderObjs.length; i++) + { + // Check if we are dealing with a file or a folder + File hostFolder = new File(servicesConfigFolder, servicesConfigFolderObjs[i]); + try + { + if (hostFolder.isDirectory() == true) + { + System.err.println("EnabledSvcsConfig()- Host folder " + hostFolder + " is directory"); + + // Now go through the services configured for this host + String[] hostFolderObjs = hostFolder.list(); + if (hostFolderObjs != null) + { + // Create a Map object to hold the service configurations for this host + Map enabledSvcsConfigMap = new HashMap(); + + for (int ii = 0; ii < hostFolderObjs.length; ii++) + { + // Check if we are dealing with a file or a folder + File serviceFolder = new File(hostFolder, hostFolderObjs[ii]); + System.err.println("EnabledSvcsConfig()- Service folder " + serviceFolder); + try + { + if (serviceFolder.isDirectory() == true) + { + System.err.println("EnabledSvcsConfig()- Service folder " + serviceFolder + " is directory"); + + // We are dealing with a folder, remember that the folder name matches the name + // of the enabled service. Check and see if there are authentication policy and + // authtoken and identoken setting files configured for it. + byte[] authPolicyData = null; + AuthTokenConfig authTokenConfig = null; + IdenTokenConfig idenTokenConfig = null; + + try + { + File policyFile = new File(serviceFolder, m_authPolicyFileName); + authPolicyData = new byte[(int) policyFile.length()]; + FileInputStream inStream = new FileInputStream(policyFile); + int bytesRead = inStream.read(authPolicyData); + inStream.close(); + if (bytesRead != authPolicyData.length) + { + System.err.println("EnabledSvcsConfig()- Error reading policy file for " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii]); + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + serviceFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString()); + } + catch (FileNotFoundException e) + { + System.err.println("EnabledSvcsConfig()- No authentication policy file for " + serviceFolder); + } + catch (IOException e) + { + System.err.println("EnabledSvcsConfig()- IOException reading " + serviceFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString()); + } + + try + { + authTokenConfig = new AuthTokenConfig(serviceFolder + File.separator + m_authTokenSettingsFileName); + } + catch (Exception e) + { + System.err.println("EnabledSvcsConfig()- Exception accessing " + serviceFolder + File.separator + m_authTokenSettingsFileName + " Exception=" + e.toString()); + } + + try + { + idenTokenConfig = new IdenTokenConfig(serviceFolder + File.separator + m_idenTokenSettingsFileName); + } + catch (Exception e) + { + System.err.println("EnabledSvcsConfig()- Exception accessing " + serviceFolder + File.separator + m_idenTokenSettingsFileName + " Exception=" + e.toString()); + } + + // Make sure that we have a policy file + if ((authPolicyData != null && authPolicyData.length != 0) + || (defaultAuthPolicyData != null && defaultAuthPolicyData.length != 0)) + { + // Instantiate SvcConfigEntry for this service and place it in our map + SvcConfigEntry svcConfigEntry = new SvcConfigEntry((authPolicyData != null && authPolicyData.length != 0) ? authPolicyData : defaultAuthPolicyData, + (authTokenConfig != null) ? authTokenConfig : defaultAuthTokenConfig, + (idenTokenConfig != null) ? idenTokenConfig : defaultIdenTokenConfig); + + // Add this entry to our map + System.err.println("EnabledSvcsConfig()- Adding entry in map for " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii]); + enabledSvcsConfigMap.put(hostFolderObjs[ii], svcConfigEntry); + } + else + { + System.err.println("EnabledSvcsConfig()- Unable to enable " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii] + " due to no configured authentication policy"); + } + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + serviceFolder + " Exception=" + e.toString()); + } + + // Add this hosts enabled services configuration map to the hosts map + m_hostsMap.put(servicesConfigFolderObjs[i], enabledSvcsConfigMap); + } + } + else + { + System.err.println("EnabledSvcsConfig()- No services configured for " + hostFolder); + } + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + hostFolder + " Exception=" + e.toString()); + } + } + } + else + { + System.err.println("EnabledSvcsConfig()- Unable to obtain services folder " + servicesConfigFolder + " objects"); + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + servicesConfigFolder + " Exception=" + e.toString()); + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + configFolder + " Exception=" + e.toString()); + } + } + + /* + * Returns true if the specified service has been enabled to use authentication + * tokens. + */ + public boolean svcEnabled(String hostName, String serviceName) + { + // First try to obtain the Map of enabled services for the host + // tbd - Should we make this case insensitive? + Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName); + if (enabledSvcsConfigMap != null) + { + return enabledSvcsConfigMap.containsKey(serviceName); + } + else + { + return false; + } + } + + /* + * Returns the data associated with the authentication policy file + * associated with the specified service. + */ + public byte[] getAuthPolicyFileDataForSvc(String hostName, String serviceName) + { + // First try to obtain the Map of enabled services for the host + // tbd - Should we make this case insensitive? + Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName); + if (enabledSvcsConfigMap != null) + { + // Retrieve SvcConfigEntry for the service from the map for the host + SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName); + if (svcConfigEntry != null) + { + return svcConfigEntry.m_authPolicyFileData; + } + else + { + return null; + } + } + else + { + return null; + } + } + + /* + * Returns the authentication token configuration associated with the + * specified service. + */ + public AuthTokenConfig getAuthTokenConfig(String hostName, String serviceName) + { + // First try to obtain the Map of enabled services for the host + // tbd - Should we make this case insensitive? + Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName); + if (enabledSvcsConfigMap != null) + { + // Retrieve SvcConfigEntry for the service from the map for the host + SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName); + if (svcConfigEntry != null) + { + return svcConfigEntry.m_authTokenConfig; + } + else + { + return null; + } + } + else + { + return null; + } + } + + /* + * Returns the identity token configuration associated with the + * specified service. + */ + public IdenTokenConfig getIdenTokenConfig(String hostName, String serviceName) + { + // First try to obtain the Map of enabled services for the host + // tbd - Should we make this case insensitive? + Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName); + if (enabledSvcsConfigMap != null) + { + // Retrieve SvcConfigEntry for the service from the map for the host + SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName); + if (svcConfigEntry != null) + { + return svcConfigEntry.m_idenTokenConfig; + } + else + { + return null; + } + } + else + { + return null; + } + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicy.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicy.java new file mode 100644 index 00000000..20654539 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicy.java @@ -0,0 +1,127 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.io.PrintWriter; +import java.util.*; + +/** + * GetAuthPolicy Class. + * + * This class processes get authentication policy requests for a particular + * service. + * + */ +public class GetAuthPolicy implements RpcMethod +{ + private SvcConfig m_svcConfig; + private EnabledSvcsConfig m_enabledSvcsConfig; + + /* + * Constructor. + */ + public GetAuthPolicy() throws Exception + { + // Nothing to do at this time + } + + /* + * Initialize the Rpc method. + */ + public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception + { + m_svcConfig = svcConfig; + m_enabledSvcsConfig = enabledSvcsConfig; + } + + /* + * Process Rpc. + */ + public void invoke(InputStream inStream, PrintWriter out) throws IOException + { + try + { + System.err.println("GetAuthPolicy.invoke()"); + + // Read and parse the GetAuthPolicyReqMsg sent from the client + GetAuthPolicyReqMsg getAuthPolicyReqMsg = new GetAuthPolicyReqMsg(inStream); + + // Verify that the service is enabled + if (m_enabledSvcsConfig.svcEnabled(getAuthPolicyReqMsg.getHostName(), getAuthPolicyReqMsg.getServiceName())) + { + // Get the auth policy for the service + byte[] authPolicy = m_enabledSvcsConfig.getAuthPolicyFileDataForSvc(getAuthPolicyReqMsg.getHostName(), + getAuthPolicyReqMsg.getServiceName()); + if (authPolicy != null) + { + // Write out the response + GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpOkStatusMsg, + ProtoDefs.httpOkStatusCode, + new String(Base64Coder.encode(authPolicy))); + out.println(getAuthPolicyRespMsg.toString()); + } + else + { + System.err.println("GetAuthPolicy.invoke()- authPolicy is null for enabled service: " + getAuthPolicyReqMsg.getServiceName()); + GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpServerErrorStatusMsg, + ProtoDefs.httpServerErrorStatusCode); + out.println(getAuthPolicyRespMsg.toString()); + } + } + else + { + // The service has not been enabled to utilize our authentication tokens + GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpNotFoundStatusMsg, + ProtoDefs.httpNotFoundStatusCode); + out.println(getAuthPolicyRespMsg.toString()); + } + } + catch (Exception e) + { + System.err.println("GetAuthPolicy.invoke()- Exception: " + e.toString()); + + // Write out the response + try + { + GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpServerErrorStatusMsg, + ProtoDefs.httpServerErrorStatusCode); + out.println(getAuthPolicyRespMsg.toString()); + } + catch (Exception e2) + { + System.err.println("GetAuthPolicy.invoke()- Exception trying to construct response msg: " + e2.toString()); + } + } + } + + /* + * Return the method id. + */ + public String getId() + { + return "GetAuthPolicy"; + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java new file mode 100644 index 00000000..73815f00 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java @@ -0,0 +1,282 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.InputStream; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * GetAuthPolicyReqMsg Class. + * + * This class deals with the message sent by Casa Client when requesting + * authenication policy to authenticate an entity to a particular service. + * The format of the the message is as follows: + * + * + * + * service name + * host name + * + * + */ +public class GetAuthPolicyReqMsg +{ + + protected String m_serviceName = null; + protected String m_hostName = null; + + /* + * Class for handling GetAuthPolicyReq msg parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_ROOT_ELEMENT_END = 1; + private final static int AWAITING_SERVICE_ELEMENT_START = 2; + private final static int AWAITING_SERVICE_ELEMENT_END = 3; + private final static int AWAITING_SERVICE_DATA = 4; + private final static int AWAITING_HOST_ELEMENT_START = 5; + private final static int AWAITING_HOST_ELEMENT_END = 6; + private final static int AWAITING_HOST_DATA = 7; + private final static int DONE_PARSING = 8; + + private GetAuthPolicyReqMsg m_GetAuthPolicyReqMsg; + private int m_state; + + /* + * Constructor + */ + public SAXHandler (GetAuthPolicyReqMsg GetAuthPolicyReqMsg) + { + super(); + + // Initialize our members + m_GetAuthPolicyReqMsg = GetAuthPolicyReqMsg; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we obtained all of the required elements + if (m_state != DONE_PARSING) + { + System.err.println("GetAuthPolicyReqMsg SAXHandler.endDocument()- Missing element"); + throw new SAXException("Missing element"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SERVICE_ELEMENT_START; + } + else + { + System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SERVICE_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.serviceElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SERVICE_DATA; + } + else + { + System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_HOST_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.hostElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_HOST_DATA; + } + else + { + System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + + break; + + default: + System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SERVICE_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.serviceElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_HOST_ELEMENT_START; + } + else + { + System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_HOST_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.hostElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ROOT_ELEMENT_END; + } + else + { + System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_SERVICE_DATA: + // Consume the data + m_GetAuthPolicyReqMsg.m_serviceName = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_SERVICE_ELEMENT_END; + break; + + case AWAITING_HOST_DATA: + // Consume the data + m_GetAuthPolicyReqMsg.m_hostName = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_HOST_ELEMENT_END; + break; + + default: + // Do nothing + break; + } + } + } + + /* + * Constructor + */ + public GetAuthPolicyReqMsg (InputStream inStream) throws Exception + { + try + { + // Parse the GetAuthPolicyReqMsg + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(this); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + } + catch (SAXException e) + { + System.err.println("GetAuthPolicyReqMsg()- Parse exception: " + e.toString()); + throw new Exception("Protocol error"); + } + } + + /* + * Method to get the service name. + */ + public String getServiceName() throws Exception + { + return m_serviceName; + } + + /* + * Method to get the host name. + */ + public String getHostName() throws Exception + { + return m_hostName; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicyRespMsg.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicyRespMsg.java new file mode 100644 index 00000000..7b122473 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicyRespMsg.java @@ -0,0 +1,111 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +/** + * GetAuthPolicyRespMsg Class. + * + * This class deals with the message sent to the Casa Client as a + * response to a get authentication token request. The format of + * the message is as follows when the response includes an + * authentication token: + * + * + * + * OK200 + * authentication policy data + * + * + * The format of the message is as follows when the response does not + * include an authentication token. + * + * + * + * status descriptionstatus code + * + * + * Plase note that the protocol utilizes the status codes defined + * in the HTTP 1.1 Specification. + * + */ +public class GetAuthPolicyRespMsg +{ + + String m_msg; + + /* + * Constructor for a msg that does not include the authentication policy. + */ + public GetAuthPolicyRespMsg ( + String statusDescription, + String statusCode) throws Exception + { + // Get a StringBuffer to help us with the construction of the message + StringBuffer sb = new StringBuffer(); + + // Start building the message + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n"); + sb.append("<" + ProtoDefs.statusElementName + ">" + + "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "" + + statusCode + "" + "\r\n"); + sb.append("" + "\r\n"); + + // The message has now been built, save it. + m_msg = sb.toString(); + } + + /* + * Constructor for a msg that includes the authentication policy. + */ + public GetAuthPolicyRespMsg ( + String statusDescription, + String statusCode, + String authPolicy) throws Exception + { + // Get a StringBuffer to help us with the construction of the message + StringBuffer sb = new StringBuffer(); + + // Start building the message + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n"); + sb.append("<" + ProtoDefs.statusElementName + ">" + + "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "" + + ProtoDefs.httpOkStatusCode + "" + "\r\n"); + sb.append("<" + ProtoDefs.authPolicyElementName + ">" + authPolicy + "" + "\r\n"); + sb.append("" + "\r\n"); + + // The message has now been built, save it. + m_msg = sb.toString(); + } + + /* + * Returns a string containing the GetAuthPolicyRespMsg. + */ + public String toString() + { + return m_msg; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java new file mode 100644 index 00000000..52ecee00 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java @@ -0,0 +1,331 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.InputStream; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * GetAuthTokReqMsg Class. + * + * This class deals with the message sent by Casa Client when requesting + * a token to authenticate an entity to a particular service. The format of + * the message is as follows: + * + * + * + * service name + * host name + * session token data + * + * + */ +public class GetAuthTokReqMsg +{ + + protected String m_serviceName = null; + protected String m_hostName = null; + protected String m_sessionToken = null; + + /* + * Class for handling GetAuthTokReq msg parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_ROOT_ELEMENT_END = 1; + private final static int AWAITING_SERVICE_ELEMENT_START = 2; + private final static int AWAITING_SERVICE_ELEMENT_END = 3; + private final static int AWAITING_SERVICE_DATA = 4; + private final static int AWAITING_HOST_ELEMENT_START = 5; + private final static int AWAITING_HOST_ELEMENT_END = 6; + private final static int AWAITING_HOST_DATA = 7; + private final static int AWAITING_SESSION_TOKEN_ELEMENT_START = 8; + private final static int AWAITING_SESSION_TOKEN_ELEMENT_END = 9; + private final static int AWAITING_SESSION_TOKEN_DATA = 10; + private final static int DONE_PARSING = 11; + + private GetAuthTokReqMsg m_GetAuthTokReqMsg; + private int m_state; + + /* + * Constructor + */ + public SAXHandler (GetAuthTokReqMsg GetAuthTokReqMsg) + { + super(); + + // Initialize our members + m_GetAuthTokReqMsg = GetAuthTokReqMsg; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we obtained all of the required elements + if (m_state != DONE_PARSING) + { + System.err.println("GetAuthTokReqMsg SAXHandler.endDocument()- Missing element"); + throw new SAXException("Missing element"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.getAuthTokRequestElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SERVICE_ELEMENT_START; + } + else + { + System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SERVICE_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.serviceElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SERVICE_DATA; + } + else + { + System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_HOST_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.hostElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_HOST_DATA; + } + else + { + System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + + break; + + case AWAITING_SESSION_TOKEN_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.sessionTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SESSION_TOKEN_DATA; + } + else + { + System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.getAuthTokRequestElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SERVICE_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.serviceElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_HOST_ELEMENT_START; + } + else + { + System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_HOST_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.hostElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SESSION_TOKEN_ELEMENT_START; + } + else + { + System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SESSION_TOKEN_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.sessionTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ROOT_ELEMENT_END; + } + else + { + System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_SERVICE_DATA: + // Consume the data + m_GetAuthTokReqMsg.m_serviceName = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_SERVICE_ELEMENT_END; + break; + + case AWAITING_HOST_DATA: + // Consume the data + m_GetAuthTokReqMsg.m_hostName = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_HOST_ELEMENT_END; + break; + + case AWAITING_SESSION_TOKEN_DATA: + // Consume the data + m_GetAuthTokReqMsg.m_sessionToken = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_SESSION_TOKEN_ELEMENT_END; + break; + + default: + // Do nothing + break; + } + } + } + + /* + * Constructor + */ + public GetAuthTokReqMsg (InputStream inStream) throws Exception + { + try + { + // Parse the GetAuthTokReqMsg + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(this); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + } + catch (SAXException e) + { + System.err.println("GetAuthTokReqMsg()- Parse exception: " + e.toString()); + throw new Exception("Protocol error"); + } + } + + /* + * Method to get the service name. + */ + public String getServiceName() throws Exception + { + return m_serviceName; + } + + /* + * Method to get the host name. + */ + public String getHostName() throws Exception + { + return m_hostName; + } + + /* + * Method to get the session token. + */ + public String getSessionToken() throws Exception + { + return m_sessionToken; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthTokRespMsg.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthTokRespMsg.java new file mode 100644 index 00000000..01dd193d --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthTokRespMsg.java @@ -0,0 +1,115 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +/** + * GetAuthTokRespMsg Class. + * + * This class deals with the message sent to the Casa Client as a + * response to a get authentication token request. The format of + * the message is as follows when the response includes an + * authentication token: + * + * + * + * OK200 + * lifetime valueauthentication token data + * + * + * The format of the message is as follows when the response does not + * include an authentication token. + * + * + * + * status descriptionstatus code + * + * + * Plase note that the protocol utilizes the status codes defined + * in the HTTP 1.1 Specification. + * + */ +public class GetAuthTokRespMsg +{ + + String m_msg; + + /* + * Constructor for a msg that does not include the authentication token. + */ + public GetAuthTokRespMsg ( + String statusDescription, + String statusCode) throws Exception + { + // Get a StringBuffer to help us with the construction of the message + StringBuffer sb = new StringBuffer(); + + // Start building the message + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n"); + sb.append("<" + ProtoDefs.statusElementName + ">" + + "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "" + + statusCode + "" + "\r\n"); + sb.append("" + "\r\n"); + + // The message has now been built, save it. + m_msg = sb.toString(); + } + + /* + * Constructor for a msg that includes the authentication token. + */ + public GetAuthTokRespMsg ( + String statusDescription, + String statusCode, + String authToken, + String authTokenLifetime) throws Exception + { + // Get a StringBuffer to help us with the construction of the message + StringBuffer sb = new StringBuffer(); + + // Start building the message + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n"); + sb.append("<" + ProtoDefs.statusElementName + ">" + + "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "" + + ProtoDefs.httpOkStatusCode + "" + "\r\n"); + sb.append("<" + ProtoDefs.authTokenElementName + ">" + + "<" + ProtoDefs.lifetimeElementName + ">" + authTokenLifetime + "" + + authToken + "" + "\r\n"); + sb.append("" + "\r\n"); + + // The message has now been built, save it. + m_msg = sb.toString(); + } + + /* + * Returns a string containing the GetAuthTokRespMsg. + */ + public String toString() + { + return m_msg; + } +} + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthToken.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthToken.java new file mode 100644 index 00000000..9f6a1a56 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthToken.java @@ -0,0 +1,146 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; + +/** + * GetAuthToken Class. + * + * This class processes requests for tokens to authenticate an entity + * to a particular service. + * + */ +public class GetAuthToken implements RpcMethod +{ + private SvcConfig m_svcConfig; + private EnabledSvcsConfig m_enabledSvcsConfig; + + /* + * Constructor. + */ + public GetAuthToken() throws Exception + { + // Nothing to do at this time + } + + /* + * Initialize the Rpc method. + */ + public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception + { + m_svcConfig = svcConfig; + m_enabledSvcsConfig = enabledSvcsConfig; + } + + /* + * Process Rpc. + */ + public void invoke(InputStream inStream, PrintWriter out) throws IOException + { + try + { + System.err.println("GetAuthToken.invoke()"); + + // Parse the GetAuthTokReqMsg sent from the client + GetAuthTokReqMsg getAuthTokReqMsg = new GetAuthTokReqMsg(inStream); + + // Verify that the service is enabled + if (m_enabledSvcsConfig.svcEnabled(getAuthTokReqMsg.getHostName(), + getAuthTokReqMsg.getServiceName())) + { + // Now create a session token (This validates the session token provided). + SessionToken sessionToken = new SessionToken(getAuthTokReqMsg.getSessionToken()); + + try + { + // Create the Authentication Token + AuthToken authToken = new AuthToken(sessionToken.getIdentId(), + sessionToken.getRealm(), + getAuthTokReqMsg.getServiceName(), + getAuthTokReqMsg.getHostName(), + m_svcConfig, + m_enabledSvcsConfig); + + // Write out the response + GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpOkStatusMsg, + ProtoDefs.httpOkStatusCode, + authToken.toString(), + authToken.getLifetime()); + out.println(getAuthTokRespMsg.toString()); + } + catch (Exception e) + { + System.err.println("GetAuthToken.invoke()- Exception: " + e.toString()); + + // Write out the response + try + { + GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpUnauthorizedStatusMsg, + ProtoDefs.httpUnauthorizedStatusCode); + out.println(getAuthTokRespMsg.toString()); + } + catch (Exception e2) + { + System.err.println("GetAuthToken.invoke()- Exception trying to construct response msg: " + e2.toString()); + } + } + } + else + { + // The service has not been enabled to utilize our authentication tokens + GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpNotFoundStatusMsg, + ProtoDefs.httpNotFoundStatusCode); + out.println(getAuthTokRespMsg.toString()); + } + } + catch (Exception e) + { + System.err.println("GetAuthToken.invoke()- Exception: " + e.toString()); + + // Write out the response + try + { + GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpServerErrorStatusMsg, + ProtoDefs.httpServerErrorStatusCode); + out.println(getAuthTokRespMsg.toString()); + } + catch (Exception e2) + { + System.err.println("GetAuthToken.invoke()- Exception trying to construct response msg: " + e2.toString()); + } + } + } + + /* + * Return the method id. + */ + public String getId() + { + return "GetAuthToken"; + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java new file mode 100644 index 00000000..d1b77f29 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java @@ -0,0 +1,294 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * IdenTokenConfig Class. + * + * This class obtains and maintains identity token configuration. + * + */ +public class IdenTokenConfig +{ + // Well known identity token configuration settings + public final static String EncryptAttributes = "EncryptAttributes"; + public final static String Attributes = "Attributes"; + + // Default configuration values + private String m_defaultEncryptAttributesValue = "false"; + private String m_defaultAttributesValue = "sn"; + + private Map m_tokenSettingsMap; + private String[] m_identityAttributes; + + /* + * Class for handling parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_SETTING_ELEMENT_START = 1; + private final static int AWAITING_SETTING_ELEMENT_DATA = 2; + private final static int AWAITING_SETTING_ELEMENT_END = 3; + private final static int DONE_PARSING = 4; + + private final static String m_rootElementName = "settings"; + + private Map m_keyMap; + private int m_state; + private String m_currentKey; + + /* + * Constructor + */ + public SAXHandler(Map keyMap) + { + super(); + + // Initialize our members + m_keyMap = keyMap; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we are not in an invalid state + if (m_state != DONE_PARSING) + { + System.err.println("IdenTokenConfig SAXHandler.endDocument()- Invalid state" + m_state); + throw new SAXException("Invalid state at endDocument"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + } + else + { + System.err.println("IdenTokenConfig SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SETTING_ELEMENT_START: + // Keep track of the key name + m_currentKey = qName; + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_DATA; + break; + + default: + System.err.println("IdenTokenConfig SAXHandler.startElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at startElement"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_SETTING_ELEMENT_DATA: + case AWAITING_SETTING_ELEMENT_END: + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + break; + + case AWAITING_SETTING_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("IdenTokenConfig SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("IdenTokenConfig SAXHandler.endElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at endElement"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Consume the data if in the right state + if (m_state == AWAITING_SETTING_ELEMENT_DATA) + { + // Consume the data and add the key to map + // tbd - Add code to aggregate attributes specified as multiple elements + m_keyMap.put(m_currentKey, new String(ch, start, length)); + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_END; + } + } + } + + /* + * Constructor which sets default configuration values. + */ + public IdenTokenConfig() throws Exception + { + System.err.println("IdenTokenConfig()- Default"); + + // Create a map to keep track of the token settings + m_tokenSettingsMap = new HashMap(); + + // Set the default settings in our map + m_tokenSettingsMap.put(Attributes, m_defaultAttributesValue); + } + + /* + * Constructor. + */ + public IdenTokenConfig(String idenTokenSettingsFileName) throws Exception + { + System.err.println("IdenTokenConfig()-"); + + // Create a map to keep track of the token settings + m_tokenSettingsMap = new HashMap(); + + try + { + // Get an input stream to read from the token settings file + File f = new File(idenTokenSettingsFileName); + FileInputStream inStream = new FileInputStream(f); + + // Parse the file + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(m_tokenSettingsMap); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + + inStream.close(); + + // Process the specified attributes + if (m_tokenSettingsMap.containsKey(Attributes) == false) + { + System.err.println("IdenTokenConfig()- Attributes not configured, defaulting them."); + m_tokenSettingsMap.put(Attributes, m_defaultAttributesValue); + } + String attributes = (String) m_tokenSettingsMap.get(Attributes); + m_identityAttributes = attributes.split(","); + } + catch (SAXException e) + { + System.err.println("IdenTokenConfig()- " + idenTokenSettingsFileName + " format error, exception: " + e.toString()); + throw new Exception("IdenTokenConfig()- authtoken.settings format error"); + } + catch (SecurityException e) + { + System.err.println("IdenTokenConfig()- SecurityException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString()); + throw new Exception("IdenTokenConfig()- Not able to access file"); + } + catch (FileNotFoundException e) + { + System.err.println("IdenTokenConfig()- File " + idenTokenSettingsFileName + " not found"); + throw new Exception("IdenTokenConfig()- File not found"); + } + catch (IOException e) + { + System.err.println("IdenTokenConfig()- IOException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString()); + throw new Exception("IdenTokenConfig()- Read error"); + } + } + + /* + * Returns the value associated with the specified setting. + */ + public String getSetting(String settingName) throws Exception + { + // Try to find the setting in our map + String value = (String) m_tokenSettingsMap.get(settingName); + if (value == null) + { + System.err.println("IdenTokenConfig.getSetting()- Did not find setting " + settingName); + + // The setting is not in our map, check if it is one to + // which we have defaults. + if (settingName.equals(EncryptAttributes) == true) + { + value = m_defaultEncryptAttributesValue; + System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_tokenSettingsMap.put(EncryptAttributes, m_defaultEncryptAttributesValue); + } + } + else + { + System.err.println("IdenTokenConfig.getSetting()- Found setting " + settingName); + System.err.println("IdenTokenConfig.getSetting()- Setting value = " + value); + } + + return value; + } + + /* + * Returns the identity attributes that must be included in the token. + */ + public String[] getAttributes() throws Exception + { + return m_identityAttributes; + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdentityToken.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdentityToken.java new file mode 100644 index 00000000..721157e7 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdentityToken.java @@ -0,0 +1,93 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +/* + * IdentityToken Interface. + * + * This is the interface implemented by Identity Token Providers. + */ +public interface IdentityToken +{ + /* + * Initialize the token with parameters. + */ + void initialize(String identityId, + String sourceName, + String targetService, + String targetHost, + SvcConfig svcConfig) throws Exception; + + /* + * Initialize the token object with encoded token string. + */ + void initialize(String encodedToken) throws Exception; + + /* + * Returns encoded token string. + * + * IMPORTANT: The token string can not contain the substring "]]>" + * within it. + */ + String getEncodedToken() throws Exception; + + /* + * Returns a string containing the identity token provider type. + */ + String getProviderType() throws Exception; + + /* + * Returns a string containing the identity id. + */ + String getIdentityId() throws Exception; + + /* + * Returns a string containing the name associated with the + * identity source. + */ + String getSourceName() throws Exception; + + /* + * Returns a string containing the url associated with the + * identity source. + */ + String getSourceUrl() throws Exception; + + /* + * Returns a string containing the name of the targeted service. + */ + String getTargetService() throws Exception; + + /* + * Returns a string containig the name of the host where the + * targeted service resides. + */ + String getTargetHost() throws Exception; + + /* + * Returns the attributes of the identity. + */ + javax.naming.directory.Attributes getAttributes() throws Exception; +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java new file mode 100644 index 00000000..5814e0f4 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java @@ -0,0 +1,257 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.Serializable; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchResult; +import javax.naming.directory.SearchControls; + +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSCredential; +import org.ietf.jgss.GSSException; +import org.ietf.jgss.GSSManager; +import org.ietf.jgss.GSSName; +import org.ietf.jgss.Oid; + +import org.bandit.ia.IAContext; + +/** + * Krb5Authenticate Class. + * + * This class implementes an authentication mechanism for + * the processing of authentication requests utilizing a + * Kerberos5 token. + * + */ +public class Krb5Authenticate implements AuthMechanism, Serializable +{ + private static final String ServicePrincipalNameSetting = "ServicePrincipalName"; + + private SvcConfig m_svcConfig; + private AuthMechConfig m_mechConfig; + + /* + * GSS Long Lived variables + */ + protected GSSManager m_manager; + protected Oid m_krb5; + protected GSSName m_svcName; + protected GSSCredential m_credential; + + /* + * Krb5 Token Class. + */ + private class Krb5Token + { + private String m_principalName = ""; + + /* + * The format of the Krb5 token is as follows: + * + * Base64.encode(GSS-API Token data)); + */ + public Krb5Token(String encodedToken, Krb5Authenticate parent) throws Exception + { + // Decode the token + char[] tokenChars = new char[encodedToken.length()]; + encodedToken.getChars(0, tokenChars.length, tokenChars, 0); + byte[] tokenBytes = Base64Coder.decode(tokenChars); + + try + { + // Create a context and validate the token + GSSContext context = parent.m_manager.createContext(parent.m_credential); + System.err.println("tokenLength = " + tokenBytes.length); + context.acceptSecContext(tokenBytes, 0, tokenBytes.length); + + // Save the principal name of the authenticated entity + GSSName principalName = context.getSrcName(); + m_principalName = principalName.toString(); + + // Clean up + context.dispose(); + } + catch (GSSException e) + { + System.err.println("Krb5Authenticate Krb5Token()- GSS Exception caught: " + e.getLocalizedMessage()); + throw new Exception("Authentication Failure"); + } + } + + /* + * Returns the name of the authenticated principal + */ + public String getPrincipalName() + { + return m_principalName; + } + } + + /* + * Constructor + */ + public Krb5Authenticate() throws Exception + { + // Nothing to do at this time + } + + /* + * Initialize the mechanism. + */ + public void init(SvcConfig svcConfig, AuthMechConfig mechConfig) throws Exception + { + m_svcConfig = svcConfig; + m_mechConfig = mechConfig; + + String servicePrincipal = mechConfig.getSetting(ServicePrincipalNameSetting); + if (servicePrincipal != null) + { + try + { + // Initalize our GSS variables + // + // Get an instance of the default GSSManager + m_manager = GSSManager.getInstance(); + + // Create an OID specifying the Krb5 mechanism + m_krb5 = new Oid("1.2.840.113554.1.2.2"); + + // Create our host based service name + m_svcName = m_manager.createName(servicePrincipal, + GSSName.NT_HOSTBASED_SERVICE, + m_krb5); + + // Now acquire our credentials + m_credential = m_manager.createCredential(m_svcName, + GSSCredential.INDEFINITE_LIFETIME, + m_krb5, + GSSCredential.ACCEPT_ONLY); + } + catch (GSSException e) + { + System.err.println("Krb5Authenticate()- GSS Exception caught: " + e.getLocalizedMessage()); + throw new Exception("Failed to instantiate needed GSS objects"); + } + } + else + { + System.err.println("Krb5Authenticate()- Service Principal Name not configured"); + throw new Exception("Service Principal Name not configured"); + } + } + + /* + * invoke() implementation. + */ + public String invoke(AuthReqMsg authReqMsg) throws Exception + { + String identId = null; + + try + { + System.err.println("Krb5Authenticate.invoke()"); + + // Now parse the Kerberos Token + Krb5Token krb5Token = new Krb5Token(authReqMsg.getAuthMechToken(), this); + + // Open a directory context and use it to identify the users + // associated with the specified surname. + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory"); + env.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile)); + env.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm()); + + DirContext ctx = new InitialDirContext(env); + + // Now search for a user with a matching kerberos principal name. + // + // Set up a search control so that the search is scoped to the sub-tree + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + // Obtain the start search context - tbd - this will be removed once the functionality flows into Bandit + String searchContext = m_svcConfig.getSetting(SvcConfig.StartSearchContext); + if (searchContext == null) + { + // A start search context was not configured, start from the root. + searchContext = ""; + } + + // Perform the search + NamingEnumeration answer = ctx.search(searchContext, + "(krbPrincipalName={0})", + new String[] {krb5Token.getPrincipalName()}, + controls); + + // Proceed based on the result of the search + if (answer.hasMore()) + { + // The search succeeded, set the identity id. + SearchResult sr = (SearchResult)answer.next(); + if (searchContext.equals("")) + { + identId = sr.getNameInNamespace(); + } + else + { + identId = sr.getName() + "," + searchContext; + } + } + } + catch (NamingException e) + { + // Log the error + System.err.println("Krb5Authenticate.invoke()- NamingException: " + e.getExplanation()); + } + catch (Exception e) + { + System.err.println("Krb5Authenticate.invoke()- Exception: " + e.toString()); + } + + // Return the authentication result + return identId; + } + + /* + * Return the mechanism id. + */ + public String getId() + { + return "Krb5Authenticate"; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5_mechanism.settings b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5_mechanism.settings new file mode 100644 index 00000000..6aa16259 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5_mechanism.settings @@ -0,0 +1,7 @@ + + + This is the authentication mechanism for the Krb5Authenticate scheme. The Krb5Authenticate scheme authenticates entities using Kerberos-V tokens. + com.novell.casa.authtoksvc.Krb5Authenticate + WEB-INF/classes + Specify the service's kerberos principal name + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Makefile.am b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Makefile.am new file mode 100644 index 00000000..34a945e4 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Makefile.am @@ -0,0 +1,63 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = + +DIST_SUBDIRS = + +JAVAFILES = ProtoDefs.java \ + AuthMechConfig.java \ + SvcConfig.java \ + IdenTokenConfig.java \ + AuthTokenConfig.java \ + EnabledSvcsConfig.java \ + AuthMechanism.java \ + Authenticate.java \ + RpcMethod.java \ + Rpc.java \ + GetAuthPolicy.java \ + Base64Coder.java \ + AuthReqMsg.java \ + AuthRespMsg.java \ + IdentityToken.java \ + CasaIdentityToken.java \ + AuthToken.java \ + GetAuthPolicyReqMsg.java \ + GetAuthPolicyRespMsg.java \ + GetAuthToken.java \ + GetAuthTokReqMsg.java \ + GetAuthTokRespMsg.java \ + Krb5Authenticate.java \ + PwdAuthenticate.java \ + SessionToken.java + +EXTRA_DIST = $(JAVAFILES) \ + Krb5_mechanism.settings \ + Pwd_mechanism.settings + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/ProtoDefs.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/ProtoDefs.java new file mode 100644 index 00000000..e878a02d --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/ProtoDefs.java @@ -0,0 +1,86 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +/* + * ProDefs Class. + * + * This class contains constants utilized in the Casa Client/Server + * protocol. + * + */ +public class ProtoDefs +{ + + /* + * XML Declaration used in the Casa Client/Server protocol + */ + public final static String xmlDeclaration = ""; + + /* + * XML Element Name Constants for the documents exchanged between the + * Casa Client and the Casa Server. + */ + public final static String authRequestElementName = "auth_req"; + public final static String authResponseElementName = "auth_resp"; + public final static String getAuthPolicyRequestElementName = "get_auth_policy_req"; + public final static String getAuthPolicyResponseElementName = "get_auth_policy_resp"; + public final static String getAuthTokRequestElementName = "get_auth_tok_req"; + public final static String getAuthTokResponseElementName = "get_auth_tok_resp"; + public final static String authMechTokenElementName = "auth_mech_token"; + public final static String statusElementName = "status"; + public final static String sessionTokenElementName = "session_token"; + public final static String authTokenElementName = "auth_token"; + public final static String authPolicyElementName = "auth_policy"; + public final static String identTokenElementName = "ident_token"; + public final static String lifetimeElementName = "lifetime"; + public final static String signatureElementName = "signature"; + public final static String typeElementName = "type"; + public final static String descriptionElementName = "description"; + public final static String serviceElementName = "service"; + public final static String hostElementName = "host"; + public final static String identIdElementName = "ident_id"; + public final static String realmElementName = "realm"; + public final static String authSourceElementName = "auth_source"; + public final static String mechanismElementName = "mechanism"; + public final static String mechanismInfoElementName = "mechanism_info"; + + /* + * Configurable operating parameters + */ + public String sessionTokenLifetime = "360"; + + /* + * HTTP Status Codes and Messages + */ + public final static String httpOkStatusCode = "200"; + public final static String httpOkStatusMsg = "OK"; + public final static String httpUnauthorizedStatusCode = "401"; + public final static String httpUnauthorizedStatusMsg = "Unauthorized"; + public final static String httpNotFoundStatusCode = "404"; + public final static String httpNotFoundStatusMsg = "Not Found"; + public final static String httpServerErrorStatusCode = "500"; + public final static String httpServerErrorStatusMsg = "Internal Server Error"; +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java new file mode 100644 index 00000000..8a2443c9 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java @@ -0,0 +1,223 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.Serializable; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.util.Hashtable; + +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.DirContext; +import javax.naming.directory.Attributes; +import javax.naming.directory.SearchResult; +import javax.naming.directory.SearchControls; +import javax.naming.NamingException; + +import org.bandit.ia.IAContext; + + +/** + * PwdAuthenticate Class. + * + * This class implementes an authentication mechanism for + * the processing of authentication requests utilizing a + * username/password token. + * + */ +public class PwdAuthenticate implements AuthMechanism, Serializable +{ + private SvcConfig m_svcConfig; + private AuthMechConfig m_mechConfig; + + /* + * Password Token Class. + */ + private class PwToken + { + private String m_username = ""; + private String m_password = ""; + + /* + * The format of the Pw token is as follows: + * + * Base64.encode(new String("username\r\n" + "password\r\n")); + */ + public PwToken(String encodedToken) throws IOException + { + // Decode the token + String token = Base64Coder.decode(encodedToken); + + BufferedReader tokenReader = new BufferedReader(new StringReader(token)); + + // The second line contains the "username" + m_username = tokenReader.readLine(); + + // The third line contains the "password" + m_password = tokenReader.readLine(); + } + + /* + * Returns the username + */ + public String getUsername() + { + return m_username; + } + + /* + * Returns the password + */ + public String getPassword() + { + return m_password; + } + } + + /* + * Constructor + */ + public PwdAuthenticate() throws Exception + { + // Nothing to do at this time + } + + /* + * Initialize the mechanism. + */ + public void init(SvcConfig svcConfig, AuthMechConfig mechConfig) throws Exception + { + m_svcConfig = svcConfig; + m_mechConfig = mechConfig; + } + + /* + * invoke() implementation. + */ + public String invoke(AuthReqMsg authReqMsg) throws Exception + { + String identId = null; + + try + { + System.err.println("PwdAuthenticate.invoke()"); + + // Now parse the PW Token + PwToken pwToken = new PwToken(authReqMsg.getAuthMechToken()); + + // Open a directory context and use it to identify the users + // associated with the specified surname. + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory"); + env.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile)); + env.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm()); + + DirContext ctx = new InitialDirContext(env); + + // Now search for a user with a matching surname. + // + // Set up a search control so that the search is scoped to the sub-tree + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + // Obtain the start search context - tbd - this will be removed once the functionality flows into Bandit + String searchContext = m_svcConfig.getSetting(SvcConfig.StartSearchContext); + if (searchContext == null) + { + // A start search context was not configured, start from the root. + searchContext = ""; + } + + // Perform the search + NamingEnumeration answer = ctx.search(searchContext, + "(cn={0})", + new String[] {pwToken.getUsername()}, + controls); + + // Enumerate through the users returned checking the password + while (answer.hasMore()) + { + SearchResult sr = (SearchResult)answer.next(); + + // Open a directory context for the user as a way of verifying its password + try + { + Hashtable env2 = new Hashtable(); + env2.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory"); + env2.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile)); + env2.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm()); + env2.put(Context.SECURITY_AUTHENTICATION, "simple"); + env2.put(Context.SECURITY_PRINCIPAL, sr.getNameInNamespace()); + env2.put(Context.SECURITY_CREDENTIALS, pwToken.getPassword()); + + if ((new InitialDirContext(env2)) != null) + { + // The password must be valid, set the identity Id. + if (searchContext.equals("")) + { + identId = sr.getName(); + } + else + { + identId = sr.getName() + "," + searchContext; + } + break; + } + } + catch (NamingException e) + { + System.err.println("PwdAuthenticate.invoke()- NamingException: " + e.getExplanation()); + } + } + } + catch (NamingException e) + { + // Log the error + System.err.println("PwdAuthenticate.invoke()- NamingException on Proxy User: " + e.getExplanation()); + } + catch (Exception e) + { + System.err.println("PwdAuthenticate.invoke()- Exception: " + e.toString()); + } + + // Return the authentication result + return identId; + } + + /* + * Return the mechanism id. + */ + public String getId() + { + return "PwdAuthenticate"; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Pwd_mechanism.settings b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Pwd_mechanism.settings new file mode 100644 index 00000000..5532e361 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Pwd_mechanism.settings @@ -0,0 +1,6 @@ + + + This is the authentication mechanism for the PwdAuthenticate scheme. The PwdAuthenticate scheme authenticates entities using username/password tokens. + com.novell.casa.authtoksvc.PwdAuthenticate + WEB-INF/classes + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Rpc.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Rpc.java new file mode 100644 index 00000000..6da2ca7c --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Rpc.java @@ -0,0 +1,285 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.util.*; + +import java.io.*; +import java.io.PrintWriter; + +import javax.servlet.*; +import javax.servlet.ServletException; +import javax.servlet.http.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +/** + * Rpc Servlet Class. + * + * This class processes Rpcs to the Authentication Token Service. + * + */ +public class Rpc extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet +{ + private static final long serialVersionUID = -8264027868130334613L; + + private String m_appFolderPath = null; + private String m_configFolderPath = null; + + protected ReconfigureThread m_reconfigureThread = null; + protected int m_reconfigureInterval; // seconds + + private Map m_methodsMap; + + /* + * Reconfigure Thread Class. + * + * This class implements a runnable thread that reconfigures an Rpc Servlet instance. + * + */ + private class ReconfigureThread implements Runnable + { + private Rpc m_rpc; + private Thread m_thread; + + /* + * Constructor. + */ + public ReconfigureThread (Rpc rpc) + { + m_rpc = rpc; + m_thread = new Thread(this); + m_thread.start(); + } + + /* + * run() implementation. + */ + public void run () + { + System.err.println("ReconfigureThread.run()- Running"); + + while (true) + { + // Sleep an ammount equal the reconfigure interval for the Rpc + try + { + m_thread.sleep(m_rpc.m_reconfigureInterval * 1000); + } + catch (InterruptedException e) { /* nothing to do */ } + + // Re-configure the Rpc servlet. + try + { + m_rpc.configureServlet(); + + // Check if it is no longer necessary to re-configure the servlet + if (m_rpc.m_reconfigureInterval == 0) + { + System.err.println("ReconfigureTask.run()- Configuration changed to no longer perform timed re-configuration"); + break; + } + } + catch (Exception e) + { + System.err.println("ReconfigureTask.run()- Exception caught during re-configure process, " + e.toString()); + } + } + } + + /* + * stop() implementation. + */ + public void stop () + { + m_thread.stop(); + } + } + + /* + * Constructor. + */ + public Rpc () + { + super(); + } + + /* + * configureServlet() implementation. + */ + protected void configureServlet () throws Exception + { + // Read service configuration + SvcConfig svcConfig = new SvcConfig(m_appFolderPath, m_configFolderPath); + + // Get the reconfigure interval + try + { + m_reconfigureInterval = Integer.parseInt(svcConfig.getSetting(SvcConfig.ReconfigureInterval)); + } + catch (NumberFormatException e) + { + System.err.println("Rpc.configureServlet()- Invalid reconfigure interval value format"); + m_reconfigureInterval = Integer.parseInt(SvcConfig.DefaultReconfigureIntervalValue); + } + + // Read enabled services configuration + EnabledSvcsConfig enabledSvcsConfig = new EnabledSvcsConfig(m_configFolderPath); + + // Create a map to keep track of the Rpc methods + Map methodsMap = new HashMap(); + + // Instantiate the Rpc Methods + RpcMethod getAuthPolicy = new GetAuthPolicy(); + getAuthPolicy.init(svcConfig, enabledSvcsConfig); + methodsMap.put(getAuthPolicy.getId(), getAuthPolicy); + + RpcMethod authenticate = new Authenticate(); + authenticate.init(svcConfig, enabledSvcsConfig); + methodsMap.put(authenticate.getId(), authenticate); + + RpcMethod getAuthToken = new GetAuthToken(); + getAuthToken.init(svcConfig, enabledSvcsConfig); + methodsMap.put(getAuthToken.getId(), getAuthToken); + + // Set the map as the methods map used by the servlet + m_methodsMap = methodsMap; + } + + /* + * init() implementation. + */ + public void init (ServletConfig config) throws ServletException + { + super.init(config); + + System.err.println("Rpc.init()"); + + try + { + // Get the path to our configuration folder + // + // First check if it has been specified via a system property + ServletContext context = config.getServletContext(); + m_appFolderPath = context.getRealPath(File.separator); + m_configFolderPath = System.getProperty("com.novell.casa.authtoksvc.config"); + if (m_configFolderPath == null) + { + // The path to the svc config folder was not specified via a system + // property, assume that it's location is off the WEB-INF folder for + // our web application. + m_configFolderPath = m_appFolderPath + "WEB-INF/conf"; + } + + // Configure ourselves + configureServlet(); + + // Check if we must start a thread to periodically reconfigure ourselves + if (m_reconfigureInterval != 0) + { + m_reconfigureThread = new ReconfigureThread(this); + } + } + catch (Exception e) + { + System.err.println("Rpc.init()- Exception caught: " + e.toString()); + throw new ServletException("Exception caught while instantiating Rpc methods"); + } + } + + /* + * destroy() implementation. + */ + public void destroy () + { + super.destroy(); + + System.err.println("Rpc.destroy()"); + + // Stop our re-configure thread + if (m_reconfigureThread != null) + { + m_reconfigureThread.stop(); + } + } + + /* + * doGet() implementation. + */ + protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + doPost(request, response); + } + + /* + * doPost() implementation. + */ + protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + // Get ready to send back a reply + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + + try + { + // Obtain the input stream and execute the requested method + InputStream inStream = request.getInputStream(); + + String requestedMethod = request.getParameter("method"); + if (requestedMethod != null) + { + // Get the necessary method + RpcMethod method = (RpcMethod) m_methodsMap.get(requestedMethod); + if (method != null) + { + // Invoke the method to process the Rpc + method.invoke(inStream, out); + } + else + { + // Unsupported method + System.err.println("Rpc.doPost()- Unsupported method"); + response.sendError(response.SC_BAD_REQUEST); + } + } + else + { + // Missing method parameter + System.err.println("Rpc.doPost()- Missing method parameter"); + response.sendError(response.SC_BAD_REQUEST); + } + } + catch (Exception e) + { + // tbd + System.err.println("Rpc.doPost()- Exception caught: " + e.toString()); + response.sendError(response.SC_INTERNAL_SERVER_ERROR); + } + + // Done sending out the reply + out.close(); + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/RpcMethod.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/RpcMethod.java new file mode 100644 index 00000000..3e23a49b --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/RpcMethod.java @@ -0,0 +1,53 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.io.PrintWriter; +import java.util.*; + + +/* + * RpcMethod Interface. + * + * This is the interface implemented by Rpc Methods. + */ +public interface RpcMethod +{ + /* + * Initialize the Rpc method. + */ + void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception; + + /* + * Process Rpc. + */ + void invoke(InputStream inStream, PrintWriter out) throws IOException; + + /* + * Return the method id. + */ + String getId(); +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SessionToken.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SessionToken.java new file mode 100644 index 00000000..7f9fc29a --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SessionToken.java @@ -0,0 +1,416 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.ByteArrayInputStream; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + + +/* +* SessionToken class. +* +* This class constructs session tokens that Casa clients can present to +* the Casa server to prove that an entity has been authenticated to +* a particular realm. The format of the session token is as follows: +* +* +* +* signature value +* lifetime value +* realm value +* identity id value +* +* +*/ +public class SessionToken +{ + + private String m_id; + private String m_realm; + private String m_lifetime; + private String m_signature; + private String m_token; + + /* + * Class for handling parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_ROOT_ELEMENT_END = 1; + private final static int AWAITING_SIGNATURE_ELEMENT_START = 2; + private final static int AWAITING_SIGNATURE_ELEMENT_END = 3; + private final static int AWAITING_SIGNATURE_DATA = 4; + private final static int AWAITING_LIFETIME_ELEMENT_START = 5; + private final static int AWAITING_LIFETIME_ELEMENT_END = 6; + private final static int AWAITING_LIFETIME_DATA = 7; + private final static int AWAITING_REALM_ELEMENT_START = 8; + private final static int AWAITING_REALM_ELEMENT_END = 9; + private final static int AWAITING_REALM_DATA = 10; + private final static int AWAITING_IDENT_ID_ELEMENT_START = 11; + private final static int AWAITING_IDENT_ID_ELEMENT_END = 12; + private final static int AWAITING_IDENT_ID_DATA = 13; + private final static int DONE_PARSING = 14; + + private SessionToken m_SessionToken; + private int m_state; + + /* + * Constructor + */ + public SAXHandler (SessionToken SessionToken) + { + super(); + + // Initialize our members + m_SessionToken = SessionToken; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we obtained all of the required elements + if (m_state != DONE_PARSING) + { + System.err.println("SessionToken SAXHandler.endDocument()- Missing element"); + throw new SAXException("Missing element"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.sessionTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SIGNATURE_ELEMENT_START; + } + else + { + System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SIGNATURE_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.signatureElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SIGNATURE_DATA; + } + else + { + System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_LIFETIME_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.lifetimeElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_LIFETIME_DATA; + } + else + { + System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + + break; + + case AWAITING_REALM_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.realmElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_REALM_DATA; + } + else + { + System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_IDENT_ID_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.identIdElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_IDENT_ID_DATA; + } + else + { + System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("SessionToken SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_ROOT_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.sessionTokenElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SIGNATURE_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.signatureElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_LIFETIME_ELEMENT_START; + } + else + { + System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_LIFETIME_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.lifetimeElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_REALM_ELEMENT_START; + } + else + { + System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_REALM_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.realmElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_IDENT_ID_ELEMENT_START; + } + else + { + System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_IDENT_ID_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.identIdElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_ROOT_ELEMENT_END; + } + else + { + System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("SessionToken SAXHandler.startElement()- State error"); + throw new SAXException("State error"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + + case AWAITING_SIGNATURE_DATA: + // Consume the data + m_SessionToken.m_signature = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_SIGNATURE_ELEMENT_END; + break; + + case AWAITING_LIFETIME_DATA: + // Consume the data + m_SessionToken.m_lifetime = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_LIFETIME_ELEMENT_END; + break; + + case AWAITING_REALM_DATA: + // Consume the data + m_SessionToken.m_realm = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_REALM_ELEMENT_END; + break; + + case AWAITING_IDENT_ID_DATA: + // Consume the data + m_SessionToken.m_id = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_IDENT_ID_ELEMENT_END; + break; + + default: + // Do nothing + break; + } + } + } + + /* + * Constructor + */ + public SessionToken(String id, String realm, String lifetime) throws Exception + { + // Save copies of the input parameters + m_id = id; + m_realm = realm; + m_lifetime = lifetime; + + // Generate a signature + // tbd - Over id, realm, and lifetime data. + m_signature = "tbd"; + + // Get a StringBuffer to help us with the construction of the token + StringBuffer sb = new StringBuffer(); + + // Start building the message + sb.append(ProtoDefs.xmlDeclaration + "\r\n"); + sb.append("<" + ProtoDefs.sessionTokenElementName + ">" + "\r\n"); + sb.append("<" + ProtoDefs.signatureElementName + ">" + m_signature + "" + "\r\n"); + sb.append("<" + ProtoDefs.lifetimeElementName + ">" + m_lifetime + "" + "\r\n"); + sb.append("<" + ProtoDefs.realmElementName + ">" + m_realm + "" + "\r\n"); + sb.append("<" + ProtoDefs.identIdElementName + ">" + m_id + "" + "\r\n"); + sb.append("" + "\r\n"); + + // Save the token + m_token = sb.toString(); + } + + /* + * Constructor given a session token string. The constructor + * validates the token as part of its processing. + */ + public SessionToken(String token) throws Exception + { + // Decode the token string + m_token = Base64Coder.decode(token); + + // Now parse the token into its elements + try + { + // Parse the SessionToken + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(this); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes()); + InputSource source = new InputSource(inStream); + xr.parse(source); + + // Verify the signature + // tbd + + // Verify that the token has not expired + // tbd + } + catch (SAXException e) + { + System.err.println("SessionToken()- Parse exception: " + e.toString()); + throw new Exception("Protocol error"); + } + } + + /* + * Returns a string containing the session token. + */ + public String toString() + { + return Base64Coder.encode(m_token); + } + + /* + * Method to get the Identity Id + */ + public String getIdentId() throws Exception + { + return m_id; + } + + /* + * Method to get the Identity Repository Reference (Realm). + */ + public String getRealm() throws Exception + { + return m_realm; + } +} diff --git a/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SvcConfig.java b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SvcConfig.java new file mode 100644 index 00000000..a9c34e50 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SvcConfig.java @@ -0,0 +1,299 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * SvcConfig Class. + * + * This class obtains and maintains the service configuration. + * + */ +public class SvcConfig +{ + // Well known service configuration settings + // + // The LifetimeShorter value is the value by which token lifetime + // values are shorten when specified to clients to make sure that + // the clients detect token expirations before issuing the tokens + // to a service for authentication purposes. + public final static String SessionTokenLifetime = "SessionTokenLifetime"; + public final static String LifetimeShorter = "LifetimeShorter"; + public final static String IdentityAbstractionConfigFile = "IAConfigFile"; + public final static String StartSearchContext = "startSearchContext"; + public final static String ConfigFolderPath = "ConfigFolderPath"; + public final static String AppRootPath = "AppRootPath"; + public final static String ReconfigureInterval = "ReconfigureInterval"; + + // Default configuration values + public final static String DefaultSessionTokenLifetimeValue = "43200"; // Seconds + public final static String DefaultLifetimeShorterValue = "5"; // Seconds + public final static String DefaultReconfigureIntervalValue = "60"; // Seconds + + private static final String m_svcSettingsFileName = "svc.settings"; + private Map m_svcSettingsMap; + + /* + * Class for handling Authentication Request parsing events. + */ + private class SAXHandler extends org.xml.sax.helpers.DefaultHandler + { + private final static int AWAITING_ROOT_ELEMENT_START = 0; + private final static int AWAITING_SETTING_ELEMENT_START = 1; + private final static int AWAITING_SETTING_ELEMENT_DATA = 2; + private final static int AWAITING_SETTING_ELEMENT_END = 3; + private final static int DONE_PARSING = 4; + + private final static String m_rootElementName = "settings"; + + private Map m_keyMap; + private int m_state; + private String m_currentKey; + + /* + * Constructor + */ + public SAXHandler(Map keyMap) + { + super(); + + // Initialize our members + m_keyMap = keyMap; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we are not in an invalid state + if (m_state != DONE_PARSING) + { + System.err.println("SvcConfig SAXHandler.endDocument()- Invalid state" + m_state); + throw new SAXException("Invalid state at endDocument"); + } + } + + /* + * startElement() implementation. + */ + public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_ROOT_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + } + else + { + System.err.println("SvcConfig SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SETTING_ELEMENT_START: + // Keep track of the key name + m_currentKey = qName; + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_DATA; + break; + + default: + System.err.println("SvcConfig SAXHandler.startElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at startElement"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_SETTING_ELEMENT_DATA: + case AWAITING_SETTING_ELEMENT_END: + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + break; + + case AWAITING_SETTING_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("SvcConfig SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("SvcConfig SAXHandler.endElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at endElement"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Consume the data if in the right state + if (m_state == AWAITING_SETTING_ELEMENT_DATA) + { + // Consume the data and add the key to map + m_keyMap.put(m_currentKey, new String(ch, start, length)); + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_END; + } + } + } + + /* + * Constructor. + */ + public SvcConfig(String appRootPath, String svcConfigPath) throws Exception + { + System.err.println("SvcConfig()-"); + + System.err.println("SvcConfig()- SvcConfigPath = " + svcConfigPath); + + // Create a map to keep track of the service settings + m_svcSettingsMap = new HashMap(); + + try + { + // Get an input stream to services settings file + File settingsFile = new File(svcConfigPath, m_svcSettingsFileName); + FileInputStream inStream = new FileInputStream(settingsFile); + + // Parse the file + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(m_svcSettingsMap); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + inStream.close(); + + // Add the application and config folder path settings to our map + m_svcSettingsMap.put(AppRootPath, appRootPath); + m_svcSettingsMap.put(ConfigFolderPath, svcConfigPath); + } + catch (SAXException e) + { + System.err.println("SvcConfig()- Parse exception: " + e.toString()); + throw new Exception("SvcConfig()- svc.settings format error"); + } + catch (SecurityException e) + { + System.err.println("SvcConfig()- SecurityException caught while accessing " + svcConfigPath + File.separator + m_svcSettingsFileName + " Exception=" + e.toString()); + } + catch (FileNotFoundException e) + { + System.err.println("SvcConfig()- File " + svcConfigPath + File.separator + m_svcSettingsFileName + " not found"); + } + catch (IOException e) + { + System.err.println("SvcConfig()- IOException caught while trying to read " + svcConfigPath + File.separator + m_svcSettingsFileName + " Exception=" + e.toString()); + } + } + + /* + * Returns the value associated with the specified setting. + */ + public String getSetting(String settingName) throws Exception + { + // Try to find the setting in our map + String value = (String) m_svcSettingsMap.get(settingName); + if (value == null) + { + System.err.println("SvcConfig.getSetting()- Did not find setting " + settingName); + + // The setting is not in our map, check if it is one to + // which we have defaults. + if (settingName.equals(SessionTokenLifetime) == true) + { + value = DefaultSessionTokenLifetimeValue; + System.err.println("SvcConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_svcSettingsMap.put(SessionTokenLifetime, DefaultSessionTokenLifetimeValue); + } + else if (settingName.equals(LifetimeShorter) == true) + { + value = DefaultLifetimeShorterValue; + System.err.println("SvcConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_svcSettingsMap.put(LifetimeShorter, DefaultLifetimeShorterValue); + } + else if (settingName.equals(ReconfigureInterval) == true) + { + value = DefaultReconfigureIntervalValue; + System.err.println("SvcConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_svcSettingsMap.put(ReconfigureInterval, DefaultReconfigureIntervalValue); + } + else if (settingName.equals(IdentityAbstractionConfigFile) == true) + { + System.err.println("SvcConfig.getSetting()- Mandatory setting " + IdentityAbstractionConfigFile + " not set"); + throw new Exception("Missing mandatory configuration setting"); + } + } + else + { + System.err.println("SvcConfig.getSetting()- Found setting " + settingName); + System.err.println("SvcConfig.getSetting()- Setting value = " + value); + + // Do some sanity checking + // tbd - Make sure that the token lifetime values are greater than the LifetimeShorter + } + + return value; + } +} \ No newline at end of file diff --git a/CASA-auth-token/java/server/AuthTokenSvc/svc.settings b/CASA-auth-token/java/server/AuthTokenSvc/svc.settings new file mode 100644 index 00000000..f028fef5 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/svc.settings @@ -0,0 +1,5 @@ + + + Replace with path to the Identity Abstraction Realms Configuration File. + 43200 + diff --git a/CASA-auth-token/java/server/AuthTokenSvc/web.xml b/CASA-auth-token/java/server/AuthTokenSvc/web.xml new file mode 100644 index 00000000..9cefa768 --- /dev/null +++ b/CASA-auth-token/java/server/AuthTokenSvc/web.xml @@ -0,0 +1,27 @@ + + + + CasaAuthTokenSvc + + + The CasaAuthTokenSvc provides authentication tokens. + + + Rpc + Rpc + + com.novell.casa.authtoksvc.Rpc + + + Rpc + /Rpc + + + index.html + index.htm + index.jsp + default.html + default.htm + default.jsp + + diff --git a/CASA-auth-token/java/server/JaasSupport/.classpath b/CASA-auth-token/java/server/JaasSupport/.classpath new file mode 100644 index 00000000..e487b600 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/CASA-auth-token/java/server/JaasSupport/.project b/CASA-auth-token/java/server/JaasSupport/.project new file mode 100644 index 00000000..cdeff8ac --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/.project @@ -0,0 +1,17 @@ + + + CasaJaasSupport + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/CASA-auth-token/java/server/JaasSupport/Makefile.am b/CASA-auth-token/java/server/JaasSupport/Makefile.am new file mode 100644 index 00000000..8c05e9c9 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/Makefile.am @@ -0,0 +1,81 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +####################################################################### + +SUBDIRS = src +DIST_SUBDIRS = src + +EXTRA_DIST = $(JAVAFILES) + +ROOT = ../.. + +LIBDIR = $(ROOT)/$(LIB) + +JAVAROOT = . +JAVAC= javac + +MODULE_NAME = CasaJaasSupport +MODULE_EXT = jar + +JAVAFILES = src/com/novell/casa/jaas/CasaLoginModule.java \ + src/com/novell/casa/jaas/CasaPrincipal.java + +BUILDDIR = build + +CLASSES = $(addprefix $(BUILDDIR)/, $(JAVAFILES:%.java=%.class)) + +LIBS = +CLASSPATH = $(LIBDIR)/java/CasaAuthToken.jar:$(LIBS) + +CUR_DIR := $(shell pwd) + +all: $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) + +$(BUILDDIR)/%.class: %.java + @echo [======== Compiling $@ ========] + $(JAVAC) -sourcepath src -classpath $(CLASSPATH) -d $(BUILDDIR)/classes $< + +$(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT): $(BUILDDIR) $(CLASSES) + @echo [======== Jarring $@ ========] + jar cvf $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) -C $(BUILDDIR)/classes . + cp $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/java/ + +$(BUILDDIR): + [ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) + [ -d $(BUILDDIR)/classes ] || mkdir -p $(BUILDDIR)/classes + [ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) + [ -d $(LIBDIR)/java ] || mkdir -p $(LIBDIR)/java + +install-exec-local: + +uninstall-local: + +#installcheck-local: install + +clean-local: + if [ -d $(BUILDDIR) ]; then rm -rf $(BUILDDIR); fi + if [ -f $(LIBDIR)/java/$(MODULE_NAME).$(MODULE_EXT) ]; then rm -f $(LIBDIR)/java/$(MODULE_NAME).$(MODULE_EXT); fi + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + rm -f Makefile + diff --git a/CASA-auth-token/java/server/JaasSupport/README b/CASA-auth-token/java/server/JaasSupport/README new file mode 100644 index 00000000..fae61bc0 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/README @@ -0,0 +1,82 @@ +/*********************************************************************** + * + * README for JaasSupport + * + ***********************************************************************/ + +INTRODUCTION + +CasaLoginModule is a JAAS login module which can be configured +to validate credentials consisting of CASA Authentication Tokens. + +CONFIGURATION + +To use CasaLoginModule for your service, set the java.security.auth.login.config +property to point to the JAAS configuration file for your application. You must +also set the org.xml.sax.driver property to point to an appropriate SAX Parser. +The Xerces SAX Parser is a good option (org.apache.xerces.parsers.SAXParser). + +The JAAS configuration file should include the following line: + +com.novell.casa.jaas.CasaLoginModule Required; + +The CasaLoginModule supports the following parameters: + +PerformUsernameCheck - This parameter when set to true tells the CasaLoginModule +that it must verify that the username is set to "CasaPrincipal". If the parameter +is not specified the username is not checked. + +CLIENT PROGRAMMING NOTES + +Clients must specify the same service name when requesting Authentication +Tokens from the CASA Client as the service name specified by the server +when opening a JAAS Context. + +SERVER PROGRAMMING NOTES + +Server applications validating credentials containing CASA Authentication +tokens can obtain information about the authenticated identity by getting +access to the CasaPrincipal that gets associated with the Subject object +returned from a successful JAAS login. The CasaPrincipal provides the +following information: username, name of the identity data source (realm), +and an URL to the identity data source. The CasaPrincipal also contains +the attributes of the authenticated identity configured as required by the +service in the Authentication Token Service. + +EXAMPLE SERVER APPLICATION + +See src/com/novell/casa/jaas/sample/SampleApp.java for an example application +using JAAS to authenticate credentials consisting of CASA Authentication Tokens. + +Note that to get the application to run you must set the path to the JAAS configuration +file as the JAVA property java.security.auth.login.config. You must also make sure that +the JAVA property org.xml.sax.driver.org is set to a valid SAX parser. The following shows +the JAVA options that you would set to run the test application: -Djava.security.auth.login. +config=/home/user/SampleApp/SampleApp.conf -Dorg.xml.sax.driver=org.apache.xerces.parsers. +SAXParser + +The SampleApp.conf file should have the following contents: + +SampleApp { + com.novell.casa.jaas.CasaLoginModule Required debug=true; +}; + +You must also include the CasaJaasSupport.jar and CasaAuthToken.jar files in the +CLASSPATH of the application. + +SECURITY CONSIDERATIONS + +CASA Authenticatication Tokens when compromised can be used to either impersonate +a user or to obtain identity information about the user. Because of this it is +important that the tokens be secured by applications making use of them. It is +recommended that the tokens be transmitted using SSL. + + + + + + + + + + diff --git a/CASA-auth-token/java/server/JaasSupport/TODO b/CASA-auth-token/java/server/JaasSupport/TODO new file mode 100644 index 00000000..87b7c803 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/TODO @@ -0,0 +1,13 @@ +/*********************************************************************** + * + * TODO for JaasSupport + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for JaasSupport. + +OUTSTANDING ITEMS + +- Change printfs used for debugging into a suitable mechanism. diff --git a/CASA-auth-token/java/server/JaasSupport/make_and_run_test.sh b/CASA-auth-token/java/server/JaasSupport/make_and_run_test.sh new file mode 100755 index 00000000..5b1a233b --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/make_and_run_test.sh @@ -0,0 +1,17 @@ +#!/bin/bash +if [ ! -d build-test ]; then + mkdir build-test + mkdir build-test/classes +else + if [ ! -d build-test/classes ]; then + mkdir build-test/classes + fi +fi +echo "*** Compiling the test application ***" +javac -sourcepath src -classpath ../../../lib/java/CasaJaasSupport.jar:../../../lib/java/CasaAuthToken.jar -d build-test/classes src/com/novell/casa/jaas/sample/SampleApp.java src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java +echo "*** Done compiling ***" +echo "" +echo "*** Starting the test application ***" +java -classpath build-test/classes:../../../lib/java/CasaJaasSupport.jar:../../../lib/java/CasaAuthToken.jar:/usr/share/java/xerces-j2.jar -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser -Djava.security.auth.login.config=src/com/novell/casa/jaas/sample/SampleApp.conf com.novell.casa.jaas.sample.SampleApp +#jdb -sourcepath src:../AuthTokenSvc/src -classpath build-test/classes:../../../lib/java/CasaJaasSupport.jar:../../../lib/java/CasaAuthToken.jar:/usr/share/java/xerces-j2.jar -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser -Djava.security.auth.login.config=src/com/novell/casa/jaas/sample/SampleApp.conf com.novell.casa.jaas.sample.SampleApp + diff --git a/CASA-auth-token/java/server/JaasSupport/src/Makefile.am b/CASA-auth-token/java/server/JaasSupport/src/Makefile.am new file mode 100644 index 00000000..00e1ef35 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = com + +DIST_SUBDIRS = com + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/Makefile.am b/CASA-auth-token/java/server/JaasSupport/src/com/Makefile.am new file mode 100644 index 00000000..34a83b0d --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = novell + +DIST_SUBDIRS = novell + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/novell/Makefile.am b/CASA-auth-token/java/server/JaasSupport/src/com/novell/Makefile.am new file mode 100644 index 00000000..2fb64053 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/novell/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = casa + +DIST_SUBDIRS = casa + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/Makefile.am b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/Makefile.am new file mode 100644 index 00000000..0c89b23b --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = jaas + +DIST_SUBDIRS = jaas + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/CasaLoginModule.java b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/CasaLoginModule.java new file mode 100644 index 00000000..51db3a0d --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/CasaLoginModule.java @@ -0,0 +1,257 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.jaas; + +import java.util.Map; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.login.FailedLoginException; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; + +import com.novell.casa.authtoksvc.AuthToken; +import com.novell.casa.authtoksvc.CasaIdentityToken; + +/* + * CasaLoginModule Class. + * + * This class implements a LoginModule which performs + * authentication via the Casa Authentication Token + * infrastructure. + * + */ +public class CasaLoginModule implements LoginModule +{ + private final static String casaUsername = "CasaIdentityUser"; + + private Subject m_subject = null; + private CasaPrincipal m_principal = null; + private CallbackHandler m_callbackHandler = null; + private Map m_sharedState = null; + private Map m_options = null; + + /* + * (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#abort() + */ + public boolean abort() throws LoginException + { + // Clear out all of our state + m_subject = null; + m_principal = null; + m_callbackHandler = null; + m_sharedState = null; + m_options = null; + + return true; + } + + /* + * (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#commit() + */ + public boolean commit() throws LoginException + { + // Check if we instantiated a principal to associate + // with the subject. + if (m_principal != null) + { + try + { + // Add our principal to the set associated with + // the subject. + m_subject.getPrincipals().add(m_principal); + return true; + } + catch (Exception e) + { + System.err.println("CasaLoginModule.commit()- Exception caught associating principal, msg: " + e.getMessage()); + throw new LoginException("Error encountered"); + } + } + else + { + // Allways return since authentication failed or was not + // performed by us. + return false; + } + } + + /* + * (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#login() + */ + public boolean login() throws LoginException + { + // Verify that a CallbackHandler was specified + if (m_callbackHandler == null) + { + System.err.println("CasaLoginModule.login()- Null CallbackHandler"); + throw new LoginException("Null CallbackHandler"); + } + + // Do not perform the username check unless configured to do it. + boolean performUsernameCheck = false; + if (m_options != null + && m_options.containsKey((String) "PerformUsernameCheck") == true) + { + String keyVal = (String) m_options.get("PerformUsernameCheck"); + if (keyVal != null && keyVal.equals("true")) + performUsernameCheck = true; + } + + if (performUsernameCheck) + { + // Verify that the username is CasaIdentityUser, for this + // we first need to obtain it. + // + // Try to obtain the user name from the shared state + String username = (String) m_sharedState.get("javax.security.auth.login.name"); + if (username == null) + { + // The usename was not stored in the shared state, request it. + try + { + NameCallback nameCallback = new NameCallback("Enter username:"); + Callback[] callbacks = new Callback[1]; + callbacks[0] = nameCallback; + m_callbackHandler.handle(callbacks); + username = nameCallback.getName(); + } + catch (Exception e) + { + System.err.println("CasaLoginModule.login()- Exception caught during nameCallback, msg: " + e.getMessage()); + } + + // Check the username + if (username == null) + return false; + else + { + // Save the retrieved username in the shared state and then check it. + m_sharedState.put("javax.security.auth.login.name", username); + if (username.equals(casaUsername) == false) + return false; + } + } + else + { + // Check the username + if (username.equals(casaUsername) == false) + return false; + } + } + + // Obtain the CasaAuthenticationToken + char[] authTokenChars = null; + try + { + PasswordCallback passwordCallback = new PasswordCallback("Enter CasaAuthenticationToken:", false); + Callback[] callbacks = new Callback[1]; + callbacks[0] = passwordCallback; + m_callbackHandler.handle(callbacks); + authTokenChars = passwordCallback.getPassword(); + } + catch (Exception e) + { + System.err.println("CasaLoginModule.login()- Exception caught during passwordCallback, msg: " + e.getMessage()); + } + + // Check the CasaAuthenticationToken + if (authTokenChars != null) + { + // Instantiate the AuthToken, this validates the token itself. + try + { + AuthToken authToken = new AuthToken(new String(authTokenChars)); + + // Instantiate the appropriate IdentityToken based on the IdentityTokenProvider type + // tbd - For now use the CasaIdentityToken + CasaIdentityToken identityToken = new CasaIdentityToken(); + identityToken.initialize(authToken.getIdentityToken()); + + // Now instantiate the CasaPrincipal + m_principal = new CasaPrincipal(identityToken); + } + catch (Exception e) + { + // The validation of one of the tokens failed + // tbd - Log + System.err.println("CasaLoginModule.login()- Exception caught during token processing, msg: " + e.getMessage()); + throw new FailedLoginException("Token validation failed"); + } + } + else + { + // Token not provided + // tbd - Log + System.err.println("CasaLoginModule.login()- Token not provided"); + throw new FailedLoginException("CasaAuthenticationToken not obtained"); + } + + // User validated + // tbd - Log + return true; + } + + /* + * (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#logout() + */ + public boolean logout() throws LoginException + { + // Check if we must try to remove our principal + // from the associated subject. + if (m_principal != null + && m_subject.isReadOnly() == false) + { + Set principalSet = m_subject.getPrincipals(); + principalSet.remove(m_principal); + } + return true; + } + + /* + * (non-Javadoc) + * @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map) + */ + public void initialize( + Subject subject, + CallbackHandler callbackHandler, + Map sharedState, + Map options) + { + // Save the input parameters for later use + m_subject = subject; + m_callbackHandler = callbackHandler; + m_sharedState = sharedState; + m_options = options; + } +} diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/CasaPrincipal.java b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/CasaPrincipal.java new file mode 100644 index 00000000..ef97808e --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/CasaPrincipal.java @@ -0,0 +1,87 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + ***********************************************************************/ + +package com.novell.casa.jaas; + +import java.security.Principal; + +import com.novell.casa.authtoksvc.IdentityToken; + +/* + * CasaPrincipal class. + * + * This class implements the principal class for + * identities authenticated by Casa. + * + */ +public class CasaPrincipal implements Principal +{ + private String m_name; + private String m_realm; + private String m_identStoreUrl; + private javax.naming.directory.Attributes m_attributes; + + /* + * Constructor + */ + public CasaPrincipal(IdentityToken identityToken) throws Exception + { + // Get the necessary information from the identity token + m_name = identityToken.getIdentityId(); + m_realm = identityToken.getSourceName(); + m_identStoreUrl = identityToken.getSourceUrl(); + m_attributes = identityToken.getAttributes(); + } + + /* + * (non-Javadoc) + * @see java.security.Principal#getName() + */ + public String getName() + { + return m_name; + } + + /* + * Returns the name associated with the source of the identity data. + */ + public String getRealm() + { + return m_realm; + } + + /* + * Returns the url associated with the source of the identity data. + */ + public String getIdentStoreUrl() + { + return m_identStoreUrl; + } + + /* + * Returns the identity attributes. + */ + public javax.naming.directory.Attributes getAttributes() + { + return m_attributes; + } +} diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/Makefile.am b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/Makefile.am new file mode 100644 index 00000000..8dec38a9 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/Makefile.am @@ -0,0 +1,39 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = + +DIST_SUBDIRS = + +JAVAFILES = CasaLoginModule.java \ + CasaPrincipal.java + + +EXTRA_DIST = $(JAVAFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleApp.conf b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleApp.conf new file mode 100644 index 00000000..c2fb8fc9 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleApp.conf @@ -0,0 +1,3 @@ +testService { + com.novell.casa.jaas.CasaLoginModule Required debug=true; +}; \ No newline at end of file diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleApp.java b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleApp.java new file mode 100644 index 00000000..0cd43c85 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleApp.java @@ -0,0 +1,193 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.jaas.sample; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Iterator; +import java.util.Set; + +import javax.naming.NamingEnumeration; +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +import com.novell.casa.jaas.CasaPrincipal; + + +/* + * This is a sample application which demonstrates the use of + * JAAS and Casa to authenticate a connection. + */ +public class SampleApp +{ + /** + * @param args + */ + public static void main(String[] args) + { + Socket sock = null; + ServerSocket listenSock = null; + + try + { + // Create a socket to listen for connections + int port = 4444; + int queueLen = 6; + System.out.println("Listen port = " + port); + listenSock = new ServerSocket(port, queueLen); + + // Service connections + while (true) + { + BufferedReader in = null; + try + { + // Wait for the next connection + System.out.println("Waiting for connection"); + sock = listenSock.accept(); + System.out.println(); + System.out.println("********Connection received*********"); + + // Get socket I/O streams + in = new BufferedReader(new InputStreamReader(sock.getInputStream())); + //PrintStream out = new PrintStream(sock.getOutputStream()); + + // Get the authentication token from the client + String authToken = in.readLine(); + //System.out.println("Token received from client, length = " + authToken.length()); + + // Authenticate the token and print out the information available to our service + // about the authenticated identity. + LoginContext lc = new LoginContext("testService", new SampleAppCallbackHandler(authToken)); + try + { + System.out.println("Authenticating the user"); + lc.login(); + + System.out.println(" Authentication succeeded"); + + // Now get the subject associated with the context + Subject subject = lc.getSubject(); + + // Now get the CasaPrincipals that represent the authenticated + // identity or identities. + Set principalSet = subject.getPrincipals(CasaPrincipal.class); + //System.out.println("The number of CasaPrincipals is: " + principalSet.size()); + Iterator principalIter = principalSet.iterator(); + System.out.println(); + System.out.println("Authenticated Identity Information"); + System.out.println(); + while (principalIter.hasNext() == true) + { + CasaPrincipal principal = (CasaPrincipal) principalIter.next(); + + // Print out information about the principal + System.out.println(" Source of the identity information: " + principal.getIdentStoreUrl()); + System.out.println(" Realm name associated with identity source: " + principal.getRealm()); + System.out.println(" Principal name (unique within identity source realm): " + principal.getName()); + System.out.println(); + System.out.println("Authenticated Identity Attributes"); + System.out.println(); + javax.naming.directory.Attributes attrs = principal.getAttributes(); + for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();) + { + javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) ae.next(); + + NamingEnumeration enumeration = attr.getAll(); + while (enumeration.hasMore()) + { + System.out.print(" Attribute Name: " + attr.getID()); + Object attrValue = enumeration.next(); + if (attrValue instanceof byte[]) + { + // The attribute value is binary data + StringBuffer buf = new StringBuffer(); + char[] hex = "0123456789ABCDEF".toCharArray(); + for (int i = 0; i < ((byte[]) attrValue).length; i++) + { + buf.append(hex[(((byte[]) attrValue)[i] >> 4) & 0xF]); + buf.append(hex[((byte[]) attrValue)[i] & 0xF]); + } + System.out.println(" :: Attribute Value: " + buf.toString()); + } + else + { + // The attribute value is contained in a string + System.out.println(" :: Attribute Value: " + (String) attrValue); + } + } + } + } + System.out.println(); + } + catch (LoginException e) + { + System.out.println(" Authentication failed, LoginException: " + e.getMessage()); + } + } + finally + { + if (sock != null) + { + sock.close(); + sock = null; + } + if (in != null) + in.close(); + } + } + } + catch (IOException e) + { + System.out.println("IOException: " + e.getMessage()); + } + catch (Exception e) + { + System.out.println("Exception: " + e.getMessage()); + } + finally + { + try + { + if (sock != null) + { + sock.close(); + } + if (listenSock != null) + { + listenSock.close(); + } + } + catch (Exception e) + { + System.out.println("Exception: " + e.getMessage()); + } + } + } +} diff --git a/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java new file mode 100644 index 00000000..990ec5b2 --- /dev/null +++ b/CASA-auth-token/java/server/JaasSupport/src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java @@ -0,0 +1,71 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +package com.novell.casa.jaas.sample; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + + +public class SampleAppCallbackHandler implements CallbackHandler +{ + private String m_authToken; + + /* + * Constructor + * + */ + public SampleAppCallbackHandler(String authToken) + { + m_authToken = authToken; + } + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + for (int i = 0; i < callbacks.length; i++) + { + if (callbacks[i] instanceof NameCallback) { + NameCallback nc = (NameCallback) callbacks[i]; + nc.setName("CasaIdentityUser"); + } else if (callbacks[i] instanceof PasswordCallback) { + PasswordCallback pc = (PasswordCallback) callbacks[i]; + //System.out.println("SampleAppCallbackHandler.handle()- Token length = " + m_authToken.length()); + char[] allChars = m_authToken.toCharArray(); + + // Remove the null terminator + char[] tokenChars = new char[allChars.length - 1]; + for (int ii = 0; ii < tokenChars.length; ii++) + tokenChars[ii] = allChars[ii]; + pc.setPassword(tokenChars); + } else { + throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); + } + } + } +} diff --git a/CASA-auth-token/java/server/Makefile.am b/CASA-auth-token/java/server/Makefile.am new file mode 100644 index 00000000..58613019 --- /dev/null +++ b/CASA-auth-token/java/server/Makefile.am @@ -0,0 +1,38 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +#SUBDIRS = AuthTokenValidate ApacheSupport PamSupport +SUBDIRS = AuthTokenValidate ApacheSupport PamSupport AuthTokenSvc JaasSupport + +DIST_SUBDIRS = AuthTokenValidate ApacheSupport PamSupport AuthTokenSvc JaasSupport + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in +