diff --git a/CASA-auth-token/client/AUTHORS b/CASA-auth-token/client/AUTHORS new file mode 100644 index 00000000..ba13017c --- /dev/null +++ b/CASA-auth-token/client/AUTHORS @@ -0,0 +1,2 @@ +Juan Carlos Luciani - jluciani@novell.com + diff --git a/CASA-auth-token/client/COPYING b/CASA-auth-token/client/COPYING new file mode 100644 index 00000000..b0ab9a23 --- /dev/null +++ b/CASA-auth-token/client/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/client/ChangeLog b/CASA-auth-token/client/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/CASA-auth-token/client/Makefile.am b/CASA-auth-token/client/Makefile.am new file mode 100644 index 00000000..c673cb71 --- /dev/null +++ b/CASA-auth-token/client/Makefile.am @@ -0,0 +1,41 @@ +####################################################################### +# +# 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 = core package + +DIST_SUBDIRS = include core 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 + if [ -d bin ]; then rm -rf bin; fi + if [ -d lib64 ]; then rm -rf lib64; fi + if [ -d bin64 ]; then rm -rf bin64; fi + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/client/NEWS b/CASA-auth-token/client/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/CASA-auth-token/client/README b/CASA-auth-token/client/README new file mode 100644 index 00000000..48d961e0 --- /dev/null +++ b/CASA-auth-token/client/README @@ -0,0 +1,241 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ +/*********************************************************************** + * + * 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 identity 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. + +REQUIREMENTS FOR BUILDING THE SOFTWARE PACKAGE ON WINDOWS + + - Install Visual Studio .NET 2003 + - Install Windows Platform SDK for Windows Server 2003 SP1 + - Register the platform sdk with VS - Start/All Programs/Windows Platform SDK for Windows Server 2003 SP1/Visual Studio Registration/Register PSDK Directories with Visual Studio + - Install Cygwin - See instructions below. + - Extract Expat-2.0.0.zip in casa source directory parent + - Install Casa + +Download and start cygwin install: +Browse to http://sources.redhat.com/cygwin/ + +Click on "Install or update now!" or "Install Cygwin now" + +Cygwin Setup: +Next + +Cygwin Setup - Choose Installation Type: +Install from Internet +Next + +Cygwin Setup - Choose Installation Directory: +Root Directory: C:\cygwin +Install For: "All Users" + +Default Text File Type: DOS + +Cygwin Setup - Select Local Package Directory: + Local Package Directory: C:\cygwin-packages + +Cygwin Setup - Select Connection Type: + Direct Connection + +Choose A Download Site: + ftp://ftp.nas.nasa.gov + +Cywin Setup - Select Packages: + Base: + defaults + + Devel: + autoconf + automake + libtool + make + pkgconfig + cvs + gcc + gcc-g++ + + Editors: + vim (optional) + + Net: + openssh + openssl + + Text: + more + + Utils: + clear (optional) + +Cygwin Setup - Create Icons: +Finish + +Edit cygwin.bat (c:\cygwin\cygwin.bat) to add a call to +%VS71COMNTOOLS%\vsvars32.bat (see example below). This sets up the +Visual Studio tools in Cygwin. + +Sample cygwin.bat: + +@echo off + +call "%VS71COMNTOOLS%\vsvars32.bat" > NUL + +C: +chdir C:\cygwin\bin + +bash --login -i + + +REQUIREMENTS FOR BUILDING THE SOFTWARE PACKAGE ON LINUX + +Install latest mono and mono-devel RPM - Obtain RPMs from +www.go-mono.org. + + +BUILDING THE SOFTWARE PACKAGE + +Windows: Start at Step 1. +Linux: Skip to Step 2. + +1. Run cygwin.bat to start up Cygwin. + +2. Generate autotools files: +./autogen.sh --prefix=/ [--enable-debug] +( is some writable directory where 'make install' will +install files for testing. + +3. To reconfigure later, or to configure software that came from a source +distribution (.tar.gz) file, use configure. +./configure --prefix/ [--enable-debug] +(run ./configure --help for more options) + +4. Select your make target, here are a few interesting ones: + +make [all] - build product files (package files not included) + +make clean - clean up files built by 'make all' + +make package - build product and package files + +make package-clean - clean up package files + +make install - install product files to specified by +--prefix during configure + +make uninstall - undo 'make install' + +make dist - build a source distribution tarball. + +make distclean - removes files to return state back to same as the +source distribution (configure, Makefile.in files, and other distributed +autotools files are not removed) + +make maintainer-clean - removes files to return state back to same as +the CVS checkout (you will need to run ./autogen.sh again before running +make again) + +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/client/TODO b/CASA-auth-token/client/TODO new file mode 100644 index 00000000..ca5a4629 --- /dev/null +++ b/CASA-auth-token/client/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 + +- Add mechanism to try communicating with ATS over port 443 if communications + over port 2645 fail. diff --git a/CASA-auth-token/client/auth.sln b/CASA-auth-token/client/auth.sln new file mode 100644 index 00000000..a0cbc949 --- /dev/null +++ b/CASA-auth-token/client/auth.sln @@ -0,0 +1,77 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Novell.Casa.Client", "client\csharp\Novell.Casa.Authtoken\Novell.Casa.Client.csproj", "{1BA1FC97-5AF1-4506-A7FD-EBFD46D361A0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClientAuth", "client\csharp\test\TestClientAuth.csproj", "{0EA635EA-97F2-4950-B36B-8151ED858DA4}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "client\windows\client.vcproj", "{7BD9A5DB-DE7D-40B7-A397-04182DC2F632}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pwd", "client\mechanisms\pwd\windows\pwd.vcproj", "{5499F624-F371-4559-B4C2-A484BCE892FD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "krb5", "client\mechanisms\krb5\windows\krb5.vcproj", "{5499F624-F371-4559-B4C2-A484BCE892FD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "client\test\windows\test.vcproj", "{6034EBF1-0838-45C4-A538-A41A31EC8F46}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "authtokenclient_msm", "package\windows\authtokenclient_msm\authtokenclient_msm.vdproj", "{C8405908-5026-4E77-B02F-9259856A17E8}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "authtokenclient_msi", "package\windows\authtokenclient_msi\authtokenclient_msi.vdproj", "{7B174382-8BE8-4F2A-A122-4FCEE849A776}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {1BA1FC97-5AF1-4506-A7FD-EBFD46D361A0}.Debug.ActiveCfg = Debug|.NET + {1BA1FC97-5AF1-4506-A7FD-EBFD46D361A0}.Debug.Build.0 = Debug|.NET + {1BA1FC97-5AF1-4506-A7FD-EBFD46D361A0}.Release.ActiveCfg = Release|.NET + {1BA1FC97-5AF1-4506-A7FD-EBFD46D361A0}.Release.Build.0 = Release|.NET + {0EA635EA-97F2-4950-B36B-8151ED858DA4}.Debug.ActiveCfg = Debug|.NET + {0EA635EA-97F2-4950-B36B-8151ED858DA4}.Debug.Build.0 = Debug|.NET + {0EA635EA-97F2-4950-B36B-8151ED858DA4}.Release.ActiveCfg = Release|.NET + {0EA635EA-97F2-4950-B36B-8151ED858DA4}.Release.Build.0 = Release|.NET + {7BD9A5DB-DE7D-40B7-A397-04182DC2F632}.Debug.ActiveCfg = Debug|Win32 + {7BD9A5DB-DE7D-40B7-A397-04182DC2F632}.Debug.Build.0 = Debug|Win32 + {7BD9A5DB-DE7D-40B7-A397-04182DC2F632}.Release.ActiveCfg = Release|Win32 + {7BD9A5DB-DE7D-40B7-A397-04182DC2F632}.Release.Build.0 = Release|Win32 + {5499F624-F371-4559-B4C2-A484BCE892FD}.Debug.ActiveCfg = Debug|Win32 + {5499F624-F371-4559-B4C2-A484BCE892FD}.Debug.Build.0 = Debug|Win32 + {5499F624-F371-4559-B4C2-A484BCE892FD}.Release.ActiveCfg = Release|Win32 + {5499F624-F371-4559-B4C2-A484BCE892FD}.Release.Build.0 = Release|Win32 + {5499F624-F371-4559-B4C2-A484BCE892FD}.Debug.ActiveCfg = Debug|Win32 + {5499F624-F371-4559-B4C2-A484BCE892FD}.Debug.Build.0 = Debug|Win32 + {5499F624-F371-4559-B4C2-A484BCE892FD}.Release.ActiveCfg = Release|Win32 + {5499F624-F371-4559-B4C2-A484BCE892FD}.Release.Build.0 = Release|Win32 + {6034EBF1-0838-45C4-A538-A41A31EC8F46}.Debug.ActiveCfg = Debug|Win32 + {6034EBF1-0838-45C4-A538-A41A31EC8F46}.Debug.Build.0 = Debug|Win32 + {6034EBF1-0838-45C4-A538-A41A31EC8F46}.Release.ActiveCfg = Release|Win32 + {6034EBF1-0838-45C4-A538-A41A31EC8F46}.Release.Build.0 = Release|Win32 + {C8405908-5026-4E77-B02F-9259856A17E8}.Debug.ActiveCfg = Debug + {C8405908-5026-4E77-B02F-9259856A17E8}.Debug.Build.0 = Debug + {C8405908-5026-4E77-B02F-9259856A17E8}.Release.ActiveCfg = Release + {C8405908-5026-4E77-B02F-9259856A17E8}.Release.Build.0 = Release + {7B174382-8BE8-4F2A-A122-4FCEE849A776}.Debug.ActiveCfg = Debug + {7B174382-8BE8-4F2A-A122-4FCEE849A776}.Debug.Build.0 = Debug + {7B174382-8BE8-4F2A-A122-4FCEE849A776}.Release.ActiveCfg = Release + {7B174382-8BE8-4F2A-A122-4FCEE849A776}.Release.Build.0 = Release + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/CASA-auth-token/client/autogen.sh b/CASA-auth-token/client/autogen.sh new file mode 100755 index 00000000..19ad55ec --- /dev/null +++ b/CASA-auth-token/client/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_auth_token_native +TEST_TYPE=-f +FILE=configure.in + +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/client/configure.in b/CASA-auth-token/client/configure.in new file mode 100644 index 00000000..5b8202fa --- /dev/null +++ b/CASA-auth-token/client/configure.in @@ -0,0 +1,285 @@ +####################################################################### +# +# 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(CASA_auth_token_client, 1.7.795,,CASA_auth_token_client) +AC_CONFIG_SRCDIR(autogen.sh) +AC_CANONICAL_SYSTEM +AM_INIT_AUTOMAKE(tar-pax) +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 + BIN=bin64 + ;; + *ia64|*) + LIB=lib + BIN=bin + ;; +esac + +AC_SUBST(LIB) +AC_SUBST(BIN) +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/windows/Makefile +package/windows/authtokenclient_msm/Makefile +package/windows/authtokenclient_msi/Makefile +package/linux/CASA_auth_token_client.spec +include/Makefile +core/Makefile +core/linux/Makefile +core/windows/Makefile +core/mechanisms/Makefile +core/mechanisms/pwd/Makefile +core/mechanisms/pwd/linux/Makefile +core/mechanisms/pwd/windows/Makefile +core/mechanisms/krb5/Makefile +core/mechanisms/krb5/linux/Makefile +core/mechanisms/krb5/windows/Makefile +]) + diff --git a/CASA-auth-token/client/core/Makefile.am b/CASA-auth-token/client/core/Makefile.am new file mode 100644 index 00000000..0dc5025c --- /dev/null +++ b/CASA-auth-token/client/core/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 = $(TARGET_OS) mechanisms + +DIST_SUBDIRS = linux windows mechanisms + +CFILES = + +EXTRA_DIST = $(CFILES) *.h client.conf + +.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/client/core/README b/CASA-auth-token/client/core/README new file mode 100644 index 00000000..60986c80 --- /dev/null +++ b/CASA-auth-token/client/core/README @@ -0,0 +1,90 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ +/*********************************************************************** + * + * README for libcasa_c_authtoken + * + ***********************************************************************/ + +INTRODUCTION + +libcasa_c_authtoken is the client auth_token engine. It is responsible for +interacting with ATSs, invoking the authentication mechanism plug-ins, and +managing the authentication token cache. libcasa_c_authtoken also provides +the Get Authentication Token API. + +CONFIGURING ADDITIONAL AUTHENTICATION MECHANISM MODULES + +libcasa_c_authtoken utilizes mechanism plug-ins for authenticating to ATSs. +The client auth_token package installs mechanisms for the support of Kerberos5 +and Username/Password authentication. To configure additional authentication mechanism +plug-ins, place their configuration file in the folder for CASA Authentication Token module +configuration. The path to this folder under linux is /etc/CASA/authtoken/client/mechanisms/. +The path to this folder under Windows is \Program Files\novell\CASA\Etc\Auth\Mechanisms\. The name of +the plug-in configuration file is related to the authentication mechanism type in the following +manner: AuthenticationMechanismTypeName.conf. + +Authentication Mechanism plug-in configuration files must must contain a directive indicating the +path to the library implementing the Authentication Mechanism (See the configuration file +for the Kr5Authenticate plug-in for an example). + +CLIENT APPLICATION PROGRAMMING NOTES + +The Get CASA Authentication Token API is defined in casa_c_authtoken.h. + +The API consists of a call to obtain authentication tokens. The caller must supply the name of the +service to which it wants to authenticate along with the name of the host where it resides. The +returned authentication token is a Base64 encoded string. + +Applications utilizing CASA Authentication Tokens as passwords in protocols that require the +transfer of user name and password credentials should verify or remove any password length limits +as the length of CASA Authentication Tokens may be over 1K bytes. The size of the CASA Authentication +Tokens is directly dependent on the amount of identity information configured as required by the +consuming service. These applications should also set the user name to "CasaPrincipal". + +For examples of code which uses the Get CASA Authentication Token API look at the test application +under the test folder. + +AUTHENTICATION MECHANISM PROGRAMMING NOTES + +The Authentication Mechanism API is defined in mech_if.h. + +For example implementations see the code for the krb5 and the pwd mechanisms. + +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/client/core/TODO b/CASA-auth-token/client/core/TODO new file mode 100644 index 00000000..07ce4dc8 --- /dev/null +++ b/CASA-auth-token/client/core/TODO @@ -0,0 +1,13 @@ +/*********************************************************************** + * + * TODO for libcasa_c_authtoken + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for libcasa_c_authtoken. + +OUTSTANDING ITEMS + +None. diff --git a/CASA-auth-token/client/core/authmech.c b/CASA-auth-token/client/core/authmech.c new file mode 100644 index 00000000..39652cb6 --- /dev/null +++ b/CASA-auth-token/client/core/authmech.c @@ -0,0 +1,343 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// AuthMechMod definition +// +typedef struct _AuthMechMod +{ + LIST_ENTRY listEntry; + char *pAuthTypeName; + int authTypeNameLen; + LIB_HANDLE libHandle; + AuthTokenIf *pAuthTokenIf; + +} AuthMechMod, *PAuthMechMod; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// AuthMechModule List and syncronizing mutex +static +LIST_ENTRY g_authMechModuleListHead = {&g_authMechModuleListHead, + &g_authMechModuleListHead}; + + +//++======================================================================= +static +CasaStatus +GetAuthTokenIf( + IN const char *pAuthTypeName, + INOUT AuthTokenIf **ppAuthTokenIf) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + ConfigIf *pModuleConfigIf; + + DbgTrace(2, "-GetAuthTokenIf- Start\n", 0); + + // Get the configuration for the module + retStatus = GetConfigInterface(mechConfigFolder, + pAuthTypeName, + &pModuleConfigIf); + if (CASA_SUCCESS(retStatus) + && CasaStatusCode(retStatus) != CASA_STATUS_OBJECT_NOT_FOUND) + { + LIST_ENTRY *pListEntry; + AuthMechMod *pAuthMechMod = NULL; + int authTypeNameLen = strlen(pAuthTypeName); + + // Look if we already have the module in our list + pListEntry = g_authMechModuleListHead.Flink; + while (pListEntry != &g_authMechModuleListHead) + { + // Get pointer to the current entry + pAuthMechMod = CONTAINING_RECORD(pListEntry, AuthMechMod, listEntry); + + // Check if this is the module that we need + if (pAuthMechMod->authTypeNameLen == authTypeNameLen + && memcmp(pAuthTypeName, pAuthMechMod->pAuthTypeName, authTypeNameLen) == 0) + { + // This is the module that we need, stop looking. + break; + } + else + { + // This is not the module that we are looking for + pAuthMechMod = NULL; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Proceed based on whether or not a module was found + if (pAuthMechMod) + { + // Module found in our list, provide the caller with its AuthTokenIf + // instance after we have incremented its reference count. + pAuthMechMod->pAuthTokenIf->addReference(pAuthMechMod->pAuthTokenIf); + *ppAuthTokenIf = pAuthMechMod->pAuthTokenIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + // Needed module not found in our list, create an entry. + pAuthMechMod = (AuthMechMod*) malloc(sizeof(*pAuthMechMod)); + if (pAuthMechMod) + { + // Allocate buffer to contain the authentication type name within the module entry + pAuthMechMod->pAuthTypeName = (char*) malloc(authTypeNameLen + 1); + if (pAuthMechMod->pAuthTypeName) + { + char *pLibraryName; + + // Initialize the library handle field + pAuthMechMod->libHandle = NULL; + + // Save the auth type name within the entry + strcpy(pAuthMechMod->pAuthTypeName, pAuthTypeName); + pAuthMechMod->authTypeNameLen = authTypeNameLen; + + // Obtain the name of the library that we must load + pLibraryName = pModuleConfigIf->getEntryValue(pModuleConfigIf, "LibraryName"); + if (pLibraryName) + { + // Load the library + pAuthMechMod->libHandle = OpenLibrary(pLibraryName); + if (pAuthMechMod->libHandle) + { + PFN_GetAuthTokenIfRtn pGetAuthTokenIfRtn; + + // Library has been loaded, now get a pointer to its GetAuthTokenInterface routine + pGetAuthTokenIfRtn = (PFN_GetAuthTokenIfRtn) GetFunctionPtr(pAuthMechMod->libHandle, + GET_AUTH_TOKEN_INTERFACE_RTN_SYMBOL); + if (pGetAuthTokenIfRtn) + { + // Now, obtain the modules AuthTokenIf. + retStatus = (pGetAuthTokenIfRtn)(pModuleConfigIf, &pAuthMechMod->pAuthTokenIf); + } + else + { + DbgTrace(0, "-GetAuthTokenIf- GetFunctionPtr\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_LIBRARY_LOAD_FAILURE); + } + } + else + { + DbgTrace(0, "-GetAuthTokenIf- OpenLibrary error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Free the buffer holding the library name + free(pLibraryName); + } + else + { + DbgTrace(0, "-GetAuthTokenIf- Library name not configured\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_CONFIGURATION_ERROR); + } + + // Check if we were successful at obtaining the AuthTokenIf instance for the + // module. + if (CASA_SUCCESS(retStatus)) + { + // Insert the entry in the list, provide the caller with its AuthTokenIf + // instance after we have incremented its reference count. + InsertTailList(&g_authMechModuleListHead, &pAuthMechMod->listEntry); + pAuthMechMod->pAuthTokenIf->addReference(pAuthMechMod->pAuthTokenIf); + *ppAuthTokenIf = pAuthMechMod->pAuthTokenIf; + } + else + { + // Failed, free resources. + free(pAuthMechMod->pAuthTypeName); + if (pAuthMechMod->libHandle) + CloseLibrary(pAuthMechMod->libHandle); + free(pAuthMechMod); + } + } + else + { + DbgTrace(0, "GetAuthTokenIf-GetAuthTokenIf- Unable to allocate buffer\n", 0); + + // Free buffer allocated for entry + free(pAuthMechMod); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-GetAuthTokenIf- Unable to allocate buffer\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + // Release config interface instance + pModuleConfigIf->releaseReference(pModuleConfigIf); + } + else + { + DbgTrace(0, "-GetAuthTokenIf- Unable to obtain config interface\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_CONFIGURATION_ERROR); + } + + DbgTrace(2, "-GetAuthTokenIf- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +GetAuthMechToken( + IN AuthContext *pAuthContext, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char **ppAuthToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + AuthTokenIf *pAuthTokenIf = NULL; + + DbgTrace(1, "-GetAuthMechToken- Start\n", 0); + + // Initialize output parameter + *ppAuthToken = NULL; + + // Obtain the appropriate token interface for the authentication type + retStatus = GetAuthTokenIf(pAuthContext->pMechanism, + &pAuthTokenIf); + if (CASA_SUCCESS(retStatus)) + { + char *pAuthToken = NULL; + int authTokenBufLen = 0; + + // We found a provider for the service, query it for the buffer size + // needed to obtain the authentication token. + retStatus = pAuthTokenIf->getAuthToken(pAuthTokenIf, + pAuthContext->pContext, + pAuthContext->pMechInfo, + pHostName, + pCredStoreScope, + pAuthToken, + &authTokenBufLen); + if (CasaStatusCode(retStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + // Allocate buffer to hold the authentication token + pAuthToken = (char*) malloc(authTokenBufLen); + if (pAuthToken) + { + // Request the token from the provider + retStatus = pAuthTokenIf->getAuthToken(pAuthTokenIf, + pAuthContext->pContext, + pAuthContext->pMechInfo, + pHostName, + pCredStoreScope, + pAuthToken, + &authTokenBufLen); + if (CASA_SUCCESS(retStatus)) + { + // Return the buffer containing the token to the caller + *ppAuthToken = pAuthToken; + } + else + { + // Free the allocated buffer + free(pAuthToken); + } + } + else + { + DbgTrace(0, "-GetAuthMechToken- Buffer allocation failure\n", 0); + } + } + + // Release token interface + pAuthTokenIf->releaseReference(pAuthTokenIf); + } + else + { + // No authentication token interface available for authentication type + DbgTrace(0, "-GetAuthMechToken- Failed to obtain auth mech token interface\n", 0); + } + + DbgTrace(1, "-GetAuthMechToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/authmsg.c b/CASA-auth-token/client/core/authmsg.c new file mode 100644 index 00000000..a55631f2 --- /dev/null +++ b/CASA-auth-token/client/core/authmsg.c @@ -0,0 +1,803 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Parse states +// +#define AWAITING_ROOT_ELEMENT_START 0x0 +#define AWAITING_ROOT_ELEMENT_END 0x1 +#define AWAITING_STATUS_ELEMENT_START 0x2 +#define AWAITING_STATUS_ELEMENT_END 0x3 +#define AWAITING_STATUS_DATA 0x4 +#define AWAITING_DESCRIPTION_ELEMENT_START 0x5 +#define AWAITING_DESCRIPTION_ELEMENT_END 0x6 +#define AWAITING_DESCRIPTION_DATA 0x7 +#define AWAITING_SESSION_TOKEN_ELEMENT_START 0x8 +#define AWAITING_SESSION_TOKEN_ELEMENT_END 0x9 +#define AWAITING_SESSION_TOKEN_DATA 0xA +#define AWAITING_LIFETIME_DATA 0xB +#define AWAITING_LIFETIME_ELEMENT_START 0xC +#define AWAITING_LIFETIME_ELEMENT_END 0xD +#define AWAITING_AUTH_TOKEN_ELEMENT_START 0xE +#define AWAITING_AUTH_TOKEN_ELEMENT_END 0xF +#define AWAITING_AUTH_TOKEN_DATA 0x10 +#define AWAITING_REALM_DATA 0x12 +#define AWAITING_REALM_ELEMENT_END 0x13 +#define DONE_PARSING 0x14 + +// +// Authentication Response Parse Structure +// +typedef struct _AuthRespParse +{ + XML_Parser p; + int state; + int elementDataProcessed; + AuthenticateResp *pAuthenticateResp; + CasaStatus status; + +} AuthRespParse, *PAuthRespParse; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//++======================================================================= +char* +BuildAuthenticateMsg( + IN AuthContext *pAuthContext, + IN char *pAuthMechToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pMsg = NULL; + int bufferSize; + + DbgTrace(1, "-BuildAuthenticateMsg- Start\n", 0); + + /* + * The format of the authentication request message is as follows: + * + * + * + * realm value + * mechanism id value + * authentication mechanism token data + * + * + */ + + // Determine the buffer size necessary to hold the msg + bufferSize = strlen(XML_DECLARATION) + + 2 // crlf + + 1 // < + + strlen(AUTH_REQUEST_ELEMENT_NAME) + + 3 // >crlf + + 1 // < + + strlen(REALM_ELEMENT_NAME) + + 1 // > + + strlen(pAuthContext->pContext) + + 2 // crlf + + 1 // < + + strlen(MECHANISM_ELEMENT_NAME) + + 1 // > + + strlen(pAuthContext->pMechanism) + + 2 // crlf + + 1 // < + + strlen(AUTH_MECH_TOKEN_ELEMENT_NAME) + + 1 // > + + strlen(pAuthMechToken) + + 2 // crlf + + 2 // null + + // Allocate the msg buffer + pMsg = (char*) malloc(bufferSize); + if (pMsg) + { + // Now build the message + memset(pMsg, 0, bufferSize); + strcat(pMsg, XML_DECLARATION); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, AUTH_REQUEST_ELEMENT_NAME); + strcat(pMsg, ">\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, REALM_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pAuthContext->pContext); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, MECHANISM_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pAuthContext->pMechanism); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, AUTH_MECH_TOKEN_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pAuthMechToken); + strcat(pMsg, "\r\n"); + strcat(pMsg, ""); + } + else + { + DbgTrace(0, "-BuildAuthenticateMsg- Buffer allocation error\n", 0); + } + + DbgTrace(1, "-BuildAuthenticateMsg- End, pMsg = %0lX\n", (long) pMsg); + + return pMsg; +} + + +//++======================================================================= +static +void XMLCALL +AuthRespStartElementHandler( + IN AuthRespParse *pAuthRespParse, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-AuthRespStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pAuthRespParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the Authentication + // Response Element. + if (strcmp(name, AUTH_RESPONSE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_STATUS_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_STATUS_ELEMENT_START: + + // In this state, we are only expecting the Status Element. + if (strcmp(name, STATUS_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_DESCRIPTION_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_DESCRIPTION_ELEMENT_START: + + // In this state, we are only expecting the Description Element. + if (strcmp(name, DESCRIPTION_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_DESCRIPTION_DATA; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_SESSION_TOKEN_ELEMENT_START: + + // In this state, we are only expecting the Session Token Element. + if (strcmp(name, SESSION_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_LIFETIME_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_ELEMENT_START: + + // In this state, we are only expecting the Lifetime Element. + if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_LIFETIME_DATA; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected state = %d\n", pAuthRespParse->state); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-AuthRespStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +ConsumeElementData( + IN AuthRespParse *pAuthRespParse, + IN const XML_Char *s, + IN int len, + INOUT char **ppElementData, + INOUT int *pElementDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + + DbgTrace(3, "-ConsumeElementData- Start\n", 0); + + // Proceed based on whether or not we have already consumed data + // for this element. + if (*ppElementData == NULL) + { + // We have not yet consumed data for this element + pAuthRespParse->elementDataProcessed = len; + + // Allocate a buffer to hold this element data (null terminated). + *ppElementData = (char*) malloc(len + 1); + if (*ppElementData) + { + memset(*ppElementData, 0, len + 1); + memcpy(*ppElementData, s, len); + + // Return the length of the element data buffer + *pElementDataLen = pAuthRespParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + char *pNewBuf; + + // We have already received token data, append this data to it. + pNewBuf = (char*) malloc(pAuthRespParse->elementDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pAuthRespParse->elementDataProcessed + len + 1); + memcpy(pNewBuf, + *ppElementData, + pAuthRespParse->elementDataProcessed); + memcpy(pNewBuf + pAuthRespParse->elementDataProcessed, s, len); + pAuthRespParse->elementDataProcessed += len; + + // Swap the buffers + free(*ppElementData); + *ppElementData = pNewBuf; + + // Return the length of the element data buffer + *pElementDataLen = pAuthRespParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + DbgTrace(3, "-ConsumeElementData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +void XMLCALL +AuthRespCharDataHandler( + IN AuthRespParse *pAuthRespParse, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-AuthRespCharDataHandler- Start\n", 0); + + // Just exit if being called to process white space + if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') + { + goto exit; + } + + // Proceed based on the state + switch (pAuthRespParse->state) + { + case AWAITING_DESCRIPTION_DATA: + case AWAITING_DESCRIPTION_ELEMENT_END: + + // Ignore the status description data for now. + // tbd + + // Advanced to the next state + pAuthRespParse->state = AWAITING_DESCRIPTION_ELEMENT_END; + break; + + case AWAITING_STATUS_DATA: + + // Set the appropriate status in the AuthenticationResp based on the + // returned status. + if (strncmp(HTTP_OK_STATUS_CODE, s, len) == 0) + { + pAuthRespParse->status = CASA_STATUS_SUCCESS; + } + else if (strncmp(HTTP_UNAUTHORIZED_STATUS_CODE, s, len) == 0) + { + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_AUTHENTICATION_FAILURE); + } + else if (strncmp(HTTP_NOT_FOUND_STATUS_CODE, s, len) == 0) + { + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_CONFIGURATION_ERROR); + } + else if (strncmp(HTTP_SERVER_ERROR_STATUS_CODE, s, len) == 0) + { + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_SERVER_ERROR); + } + else + { + DbgTrace(0, "-AuthRespCharDataHandler- Un-expected status\n", 0); + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Advanced to the next state + pAuthRespParse->state = AWAITING_STATUS_ELEMENT_END; + break; + + case AWAITING_LIFETIME_DATA: + + // Convert the lifetime string to a numeric value + pAuthRespParse->pAuthenticateResp->tokenLifetime = dtoul(s, len); + + // Advanced to the next state + pAuthRespParse->state = AWAITING_LIFETIME_ELEMENT_END; + break; + + case AWAITING_SESSION_TOKEN_DATA: + case AWAITING_SESSION_TOKEN_ELEMENT_END: + + // Consume the data + pAuthRespParse->status = ConsumeElementData(pAuthRespParse, + s, + len, + &pAuthRespParse->pAuthenticateResp->pToken, + &pAuthRespParse->pAuthenticateResp->tokenLen); + if (CASA_SUCCESS(pAuthRespParse->status)) + { + // Advanced to the next state + pAuthRespParse->state = AWAITING_SESSION_TOKEN_ELEMENT_END; + } + else + { + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-AuthRespCharDataHandler- Un-expected state = %d\n", pAuthRespParse->state); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-AuthRespCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +AuthRespEndElementHandler( + IN AuthRespParse *pAuthRespParse, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-AuthRespEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pAuthRespParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the Authentication + // Response Element. + if (strcmp(name, AUTH_RESPONSE_ELEMENT_NAME) == 0) + { + // Done. + pAuthRespParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-AuthRespEndHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_DESCRIPTION_ELEMENT_END: + + // In this state, we are only expecting the Description Element. + if (strcmp(name, DESCRIPTION_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_STATUS_DATA; + } + else + { + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_STATUS_ELEMENT_END: + + // In this state, we are only expecting the Status Element. + if (strcmp(name, STATUS_ELEMENT_NAME) == 0) + { + // Good, advance to the next state based on the status code. + if (CASA_SUCCESS(pAuthRespParse->status)) + { + // The request completed successfully + pAuthRespParse->state = AWAITING_SESSION_TOKEN_ELEMENT_START; + } + else + { + pAuthRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + } + else + { + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_ELEMENT_END: + + // In this state, we are only expecting the Lifetime Element. + if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_SESSION_TOKEN_DATA; + } + else + { + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_SESSION_TOKEN_ELEMENT_END: + + // In this state, we are only expecting the Session Token Element. + if (strcmp(name, SESSION_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected state = %d\n", pAuthRespParse->state); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-AuthRespEndElementHandler- End\n", 0); +} + + +//++======================================================================= +CasaStatus +CreateAuthenticateResp( + IN char *pRespMsg, + IN int respLen, + INOUT AuthenticateResp **ppAuthenticateResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + AuthRespParse authRespParse = {0}; + AuthenticateResp *pAuthenticateResp; + + DbgTrace(1, "-CreateAuthenticateResp- Start\n", 0); + + /* + * When an authentication request is processed successfully, the server replies to + * the client with a message with the following format: + * + * + * + * ok200 + * lifetime valuesession token data + * + * + * When an authentication request fails to be successfully processed, the server + * responds with an error and an error description string. The message format of + * an unsuccessful reply is as follows: + * + * + * + * status descriptionstatus code + * + * + * Plase note that the protocol utilizes the status codes defined + * in the HTTP 1.1 Specification. + * + */ + + // Allocate AuthenticateResp object + pAuthenticateResp = malloc(sizeof(*pAuthenticateResp)); + if (pAuthenticateResp) + { + XML_Parser p; + + // Initialize the AuthenticateResp object and set it in the + // authentication response parse oject. + memset(pAuthenticateResp, 0, sizeof(*pAuthenticateResp)); + authRespParse.pAuthenticateResp = pAuthenticateResp; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + authRespParse.p = p; + + // Initialize the status within the parse object + authRespParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + (XML_StartElementHandler) AuthRespStartElementHandler, + (XML_EndElementHandler) AuthRespEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, (XML_CharacterDataHandler) AuthRespCharDataHandler); + + + // Set our user data + XML_SetUserData(p, &authRespParse); + + // Parse the document + if (XML_Parse(p, pRespMsg, respLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (authRespParse.state == DONE_PARSING) + { + // The parse operation succeded, obtain the status returned + // by the server. + retStatus = authRespParse.status; + } + else + { + DbgTrace(0, "-CreateAuthenticateResp- Parse operation did not complete\n", 0); + + // Check if a status has been recorded + if (authRespParse.status != CASA_STATUS_SUCCESS) + { + retStatus = authRespParse.status; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + } + else + { + DbgTrace(0, "-CreateAuthenticateResp- Parse error %d\n", XML_GetErrorCode(p)); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + + // Free the parser + XML_ParserFree(p); + } + else + { + DbgTrace(0, "-CreateAuthenticateResp- Parser creation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Return the AuthenticationResp object to the caller if necessary + if (CASA_SUCCESS(retStatus)) + { + *ppAuthenticateResp = pAuthenticateResp; + } + else + { + free(pAuthenticateResp); + } + } + else + { + DbgTrace(0, "-CreateAuthenticateResp- Memory allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-CreateAuthenticateResp- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +RelAuthenticateResp( + IN AuthenticateResp *pAuthenticateResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-RelAuthenticateResp- Start\n", 0); + + // Free the resources associated with the object + if (pAuthenticateResp->pToken) + free(pAuthenticateResp->pToken); + + free(pAuthenticateResp); + + DbgTrace(1, "-RelAuthenticateResp- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/authpolicy.c b/CASA-auth-token/client/core/authpolicy.c new file mode 100644 index 00000000..9abeab7e --- /dev/null +++ b/CASA-auth-token/client/core/authpolicy.c @@ -0,0 +1,804 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Parse states +// +#define AWAITING_ROOT_ELEMENT_START 0x0 +#define AWAITING_ROOT_ELEMENT_END 0x1 +#define AWAITING_AUTH_POLICY_ELEMENT_START 0x2 +#define AWAITING_AUTH_POLICY_ELEMENT_END 0x3 +#define AWAITING_AUTH_POLICY_DATA 0x4 +#define AWAITING_AUTH_SOURCE_ELEMENT_START 0x5 +#define AWAITING_AUTH_SOURCE_ELEMENT_END 0x6 +#define AWAITING_AUTH_SOURCE_CHILD_START 0x7 +#define AWAITING_REALM_DATA 0x8 +#define AWAITING_REALM_ELEMENT_END 0x9 +#define AWAITING_MECHANISM_DATA 0xA +#define AWAITING_MECHANISM_ELEMENT_END 0xB +#define AWAITING_MECHANISM_INFO_DATA 0xC +#define AWAITING_MECHANISM_INFO_ELEMENT_END 0xD +#define AWAITING_UNKNOWN_DATA 0xE +#define AWAITING_UNKNOWN_ELEMENT_END 0xF +#define DONE_PARSING 0x10 + +// +// Authentication Policy Parse Structure +// +typedef struct _AuthPolicyParse +{ + XML_Parser p; + int state; + int elementDataProcessed; + AuthPolicy *pAuthPolicy; + CasaStatus status; + +} AuthPolicyParse, *PAuthPolicyParse; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//++======================================================================= +static +void XMLCALL +AuthPolicyStartElementHandler( + IN AuthPolicyParse *pAuthPolicyParse, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-AuthPolicyStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pAuthPolicyParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the Authentication + // Policy Element. + if (strcmp(name, AUTH_POLICY_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthPolicyStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_SOURCE_ELEMENT_START: + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the start of an Authentication + // Source Element. + if (strcmp(name, AUTH_SOURCE_ELEMENT_NAME) == 0) + { + AuthContext *pAuthContext; + + // Create an authentication context structure + pAuthContext = (AuthContext*) malloc(sizeof(AuthContext)); + if (pAuthContext) + { + // Initialize the allocated AuthContext structure and associate it + // with the AuthPolicy structure. + memset(pAuthContext, 0, sizeof(*pAuthContext)); + InsertTailList(&pAuthPolicyParse->pAuthPolicy->authContextListHead, &pAuthContext->listEntry); + + // Good, advance to the next state. + pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; + } + else + { + DbgTrace(0, "-AuthPolicyStartElementHandler- Buffer allocation error\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + } + else + { + DbgTrace(0, "-AuthPolicyStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_SOURCE_CHILD_START: + + // Proceed based on the name of the element + if (strcmp(name, REALM_ELEMENT_NAME) == 0) + { + // Advance to the next state. + pAuthPolicyParse->state = AWAITING_REALM_DATA; + } + else if (strcmp(name, MECHANISM_ELEMENT_NAME) == 0) + { + // Advance to the next state. + pAuthPolicyParse->state = AWAITING_MECHANISM_DATA; + } + else if (strcmp(name, MECHANISM_INFO_ELEMENT_NAME) == 0) + { + // Advance to the next state. + pAuthPolicyParse->state = AWAITING_MECHANISM_INFO_DATA; + } + else if (strcmp(name, AUTH_SOURCE_ELEMENT_NAME) == 0) + { + // We are starting a new auth source entry, create an authentication + // context structure to hold its information. + AuthContext *pAuthContext; + + // Create an authentication context structure + pAuthContext = (AuthContext*) malloc(sizeof(AuthContext)); + if (pAuthContext) + { + // Initialize the allocated AuthContext structure and associate it + // with the AuthPolicy structure. + memset(pAuthContext, 0, sizeof(*pAuthContext)); + InsertTailList(&pAuthPolicyParse->pAuthPolicy->authContextListHead, &pAuthContext->listEntry); + } + else + { + DbgTrace(0, "-AuthPolicyStartElementHandler- Buffer allocation error\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + } + else + { + // Advance to the next state. + pAuthPolicyParse->state = AWAITING_UNKNOWN_DATA; + } + break; + + default: + DbgTrace(0, "-AuthPolicyStartElementHandler- Un-expected state = %d\n", pAuthPolicyParse->state); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-AuthPolicyStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +ConsumeElementData( + IN AuthPolicyParse *pAuthPolicyParse, + IN const XML_Char *s, + IN int len, + INOUT char **ppElementData, + INOUT int *pElementDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + + DbgTrace(3, "-ConsumeElementData- Start\n", 0); + + // Proceed based on whether or not we have already consumed data + // for this element. + if (*ppElementData == NULL) + { + // We have not yet consumed data for this element + pAuthPolicyParse->elementDataProcessed = len; + + // Allocate a buffer to hold this element data (null terminated). + *ppElementData = (char*) malloc(len + 1); + if (*ppElementData) + { + memset(*ppElementData, 0, len + 1); + memcpy(*ppElementData, s, len); + + // Return the length of the element data buffer + *pElementDataLen = pAuthPolicyParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + char *pNewBuf; + + // We have already received token data, append this data to it. + pNewBuf = (char*) malloc(pAuthPolicyParse->elementDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pAuthPolicyParse->elementDataProcessed + len + 1); + memcpy(pNewBuf, + *ppElementData, + pAuthPolicyParse->elementDataProcessed); + memcpy(pNewBuf + pAuthPolicyParse->elementDataProcessed, s, len); + pAuthPolicyParse->elementDataProcessed += len; + + // Swap the buffers + free(*ppElementData); + *ppElementData = pNewBuf; + + // Return the length of the element data buffer + *pElementDataLen = pAuthPolicyParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + DbgTrace(3, "-ConsumeElementData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +void XMLCALL +AuthPolicyCharDataHandler( + IN AuthPolicyParse *pAuthPolicyParse, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + AuthContext *pAuthContext; + + DbgTrace(2, "-AuthPolicyCharDataHandler- Start\n", 0); + + // Just exit if being called to process white space + if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') + { + goto exit; + } + + // Proceed based on the state + switch (pAuthPolicyParse->state) + { + case AWAITING_REALM_DATA: + + // Get access to the AuthContext at the tail of the list + pAuthContext = CONTAINING_RECORD(pAuthPolicyParse->pAuthPolicy->authContextListHead.Blink, + AuthContext, + listEntry); + + // Consume the data + pAuthPolicyParse->status = ConsumeElementData(pAuthPolicyParse, + s, + len, + &pAuthContext->pContext, + &pAuthContext->contextLen); + if (CASA_SUCCESS(pAuthPolicyParse->status)) + { + // Advanced to the next state + pAuthPolicyParse->state = AWAITING_REALM_ELEMENT_END; + } + else + { + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_MECHANISM_DATA: + case AWAITING_MECHANISM_ELEMENT_END: + + // Get access to the AuthContext at the tail of the list + pAuthContext = CONTAINING_RECORD(pAuthPolicyParse->pAuthPolicy->authContextListHead.Blink, + AuthContext, + listEntry); + + // Consume the data + pAuthPolicyParse->status = ConsumeElementData(pAuthPolicyParse, + s, + len, + &pAuthContext->pMechanism, + &pAuthContext->mechanismLen); + if (CASA_SUCCESS(pAuthPolicyParse->status)) + { + // Advanced to the next state + pAuthPolicyParse->state = AWAITING_MECHANISM_ELEMENT_END; + } + else + { + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_MECHANISM_INFO_DATA: + case AWAITING_MECHANISM_INFO_ELEMENT_END: + + // Get access to the AuthContext at the tail of the list + pAuthContext = CONTAINING_RECORD(pAuthPolicyParse->pAuthPolicy->authContextListHead.Blink, + AuthContext, + listEntry); + + // Consume the data + pAuthPolicyParse->status = ConsumeElementData(pAuthPolicyParse, + s, + len, + &pAuthContext->pMechInfo, + &pAuthContext->mechInfoLen); + if (CASA_SUCCESS(pAuthPolicyParse->status)) + { + // Advanced to the next state + pAuthPolicyParse->state = AWAITING_MECHANISM_INFO_ELEMENT_END; + } + else + { + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_UNKNOWN_DATA: + case AWAITING_UNKNOWN_ELEMENT_END: + + // Just advance the state + pAuthPolicyParse->state = AWAITING_UNKNOWN_ELEMENT_END; + break; + + default: + DbgTrace(0, "-AuthPolicyCharDataHandler- Un-expected state = %d\n", pAuthPolicyParse->state); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-AuthPolicyCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +AuthPolicyEndElementHandler( + IN AuthPolicyParse *pAuthPolicyParse, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + AuthContext *pAuthContext; + + DbgTrace(2, "-AuthPolicyEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pAuthPolicyParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the Authentication + // Policy Element. + if (strcmp(name, AUTH_POLICY_ELEMENT_NAME) == 0) + { + // Done. + pAuthPolicyParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_SOURCE_CHILD_START: + + // In this state, we are only expecting the Authentication + // Source Response Element. + if (strcmp(name, AUTH_SOURCE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthPolicyParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-AuthPolicyEndHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_REALM_ELEMENT_END: + + // In this state, we are only expecting the Realm Element. + if (strcmp(name, REALM_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; + } + else + { + DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_MECHANISM_ELEMENT_END: + + // In this state, we are only expecting the Mechanism Element. + if (strcmp(name, MECHANISM_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; + } + else + { + DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_MECHANISM_INFO_DATA: + + // Get access to the AuthContext at the tail of the list + pAuthContext = CONTAINING_RECORD(pAuthPolicyParse->pAuthPolicy->authContextListHead.Blink, + AuthContext, + listEntry); + + // There was no mechanism info data. Set it to an empty string. + pAuthContext->pMechInfo = (char*) malloc(1); + if (pAuthContext->pMechInfo) + { + *pAuthContext->pMechInfo = '\0'; + } + else + { + DbgTrace(0, "-AuthPolicyEndElementHandler- Buffer allocation failure\n", 0); + pAuthPolicyParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + break; + } + // Fall through + + case AWAITING_MECHANISM_INFO_ELEMENT_END: + + // In this state, we are only expecting the Mechanism Info Element. + if (strcmp(name, MECHANISM_INFO_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; + } + else + { + DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + } + break; + + case AWAITING_UNKNOWN_ELEMENT_END: + + // Advance to the next state. + pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; + break; + + default: + DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected state = %d\n", pAuthPolicyParse->state); + XML_StopParser(pAuthPolicyParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-AuthPolicyEndElementHandler- End\n", 0); +} + + +//++======================================================================= +CasaStatus +CreateAuthPolicy( + IN char *pEncodedData, + IN int encodedDataLen, + INOUT AuthPolicy **ppAuthPolicy) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + AuthPolicy *pAuthPolicy = NULL; + AuthPolicyParse authPolicyParse = {0}; + char *pData = NULL; + int dataLen = 0; + + DbgTrace(1, "-CreateAuthPolicy- Start\n", 0); + + /* + * An authentication policy document has the following format: + * + * + * + * + * realm name + * authentication mechanism type + * authentication mechanism context data + * + * ... + * + * + * The authentication policy document can contain multiple auth_source + * elements. These auth_source elements can be for different authentication + * sources or for the same authentication source but specifying a different + * authentication mechanism. The mechanism_info element is optional. + * + * The following is a sample authentication policy document: + * + * + * + * + * Corp_eDirTree + * Krb5Authenticate + * host/hostname + * + * + * Corp_eDirTree + * PwdAuthenticate + * + * + * + * + * This authentication policy would tell the CASA client that it can + * authenticate to the CASA Authentication Token Service using + * credentials for the Corp_eDirTree and utilizing either the + * Krb5 authentication mechanism or the Pwd authentication mechanism. + * The Krb5 authentication mechanism context data specifies the + * name of the Kerberos service principal. + * + */ + + // Initialize output parameter + *ppAuthPolicy = NULL; + + // Decode the data + retStatus = DecodeData(pEncodedData, + encodedDataLen, + (void**) &pData, + &dataLen); + if (CASA_SUCCESS(retStatus)) + { + // Allocate space for the AuthPolicy structure + pAuthPolicy = (AuthPolicy*) malloc(sizeof(*pAuthPolicy)); + if (pAuthPolicy) + { + XML_Parser p; + + // Initialize the AuthPolicy object + memset(pAuthPolicy, 0, sizeof(*pAuthPolicy)); + InitializeListHead(&pAuthPolicy->authContextListHead); + + // Set the AuthPolicy object in the parse object + authPolicyParse.pAuthPolicy = pAuthPolicy; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + authPolicyParse.p = p; + + // Initialize the status within the parse object + authPolicyParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + (XML_StartElementHandler) AuthPolicyStartElementHandler, + (XML_EndElementHandler) AuthPolicyEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, (XML_CharacterDataHandler) AuthPolicyCharDataHandler); + + // Set our user data + XML_SetUserData(p, &authPolicyParse); + + // Parse the document + if (XML_Parse(p, pData, dataLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (authPolicyParse.state == DONE_PARSING) + { + // The parse operation succeded + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-CreateAuthPolicy- Parse operation did not complete\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + else + { + DbgTrace(0, "-CreateAuthPolicy- Parse error %d\n", XML_GetErrorCode(p)); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + + // Free the parser + XML_ParserFree(p); + } + else + { + DbgTrace(0, "-CreateAuthPolicy- Parser creation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Return the AuthPolicy object to the caller if necessary + if (CASA_SUCCESS(retStatus)) + { + *ppAuthPolicy = pAuthPolicy; + + // Forget about the AuthPolicy object so that it is not release down below + pAuthPolicy = NULL; + } + } + else + { + DbgTrace(0, "-CreateAuthPolicy- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-CreateAuthPolicy- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Release necessary allocated resources + if (pAuthPolicy) + RelAuthPolicy(pAuthPolicy); + + if (pData) + free(pData); + + DbgTrace(1, "-CreateAuthPolicy- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +RelAuthPolicy( + IN AuthPolicy *pAuthPolicy) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + LIST_ENTRY *pListEntry; + + DbgTrace(1, "-RelAuthPolicy- Start\n", 0); + + // Free all of the associated AuthContexts + pListEntry = pAuthPolicy->authContextListHead.Flink; + while (pListEntry != &pAuthPolicy->authContextListHead) + { + AuthContext *pAuthContext; + + // Get pointer to AuthContext structure + pAuthContext = CONTAINING_RECORD(pListEntry, AuthContext, listEntry); + + // Free associated buffers + if (pAuthContext->pContext) + free(pAuthContext->pContext); + + if (pAuthContext->pMechanism) + free(pAuthContext->pMechanism); + + if (pAuthContext->pMechInfo) + free(pAuthContext->pMechInfo); + + // Remove the entry from the list + RemoveEntryList(&pAuthContext->listEntry); + + // Free the AuthContext + free(pAuthContext); + + // Advance to the next entry + pListEntry = pAuthPolicy->authContextListHead.Flink; + } + + // Free the AuthPolicy + free(pAuthPolicy); + + DbgTrace(1, "-RelAuthPolicy- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/cache.c b/CASA-auth-token/client/core/cache.c new file mode 100644 index 00000000..d6bee9a2 --- /dev/null +++ b/CASA-auth-token/client/core/cache.c @@ -0,0 +1,588 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" +#include + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +HANDLE g_hCASAContext; + + +//++======================================================================= +AuthCacheEntry* +CreateAuthTokenCacheEntry( + IN const char *pCacheKey, + IN const char *pGroupOrHostName, + IN CasaStatus status, + IN char *pToken, + IN int entryLifetime, // seconds (0 == Lives forever) + IN void *pCredStoreScope + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"}; + SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"}; + int32_t tokenSize, entrySize, keySize; + AuthCacheEntry *pEntry = NULL; + char *pKey; + + DbgTrace(1, "-CreateAuthTokenCacheEntry- Start\n", 0); + + if (status == CASA_STATUS_SUCCESS) + { + tokenSize = (uint32_t) strlen(pToken); + } + else + { + tokenSize = 0; + } + + entrySize = tokenSize + sizeof(AuthCacheEntry); + + // Allocate space for the entry + // The AuthCacheEntry structure contains room for the tokens NULL terminator + pEntry = (AuthCacheEntry*) malloc(entrySize); + if (pEntry) + { + // Set the status + pEntry->status = status; + + if (pEntry->status == CASA_STATUS_SUCCESS) + { + memcpy(&pEntry->token[0], pToken, tokenSize); + } + + pEntry->token[tokenSize] = '\0'; + + // Set the time when the entry was added to the cache + pEntry->creationTime = GetTickCount(); + + // First determine the time when the entry is due to expire + if (entryLifetime != 0) + { + pEntry->expirationTime = pEntry->creationTime + (entryLifetime * 1000); + pEntry->doesNotExpire = false; + } + else + { + // The entry does not expire + pEntry->expirationTime = 0; + pEntry->doesNotExpire = true; + } + + keySize = (uint32_t)strlen(pCacheKey) + (uint32_t)strlen(pGroupOrHostName) + 2; + + pKey = malloc(keySize); + + if (pKey) + { + strncpy(pKey, pCacheKey, keySize); + strncat(pKey, "@", keySize); + strncat(pKey, pGroupOrHostName, keySize); + + retStatus = miCASAWriteBinaryKey(g_hCASAContext, + 0, + &sessionKeyChain, + &sharedId, + (SS_UTF8_T*) pKey, + keySize, + (uint8_t *) pEntry, + (uint32_t*) &entrySize, + NULL, + (SSCS_EXT_T*) pCredStoreScope); + + + free(pKey); + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-CreateAuthTokenCacheEntry- End, pEntry = %0lX\n", (long) pEntry); + + return pEntry; +} + + +//++======================================================================= +AuthCacheEntry* +CreateSessionTokenCacheEntry( + IN const char *pCacheKey, + IN CasaStatus status, + IN char *pToken, + IN int entryLifetime, // seconds (0 == Lives forever) + IN void *pCredStoreScope + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"}; + SSCS_SECRET_ID_T sharedId = {20, "CASA_SESSION_TOKENS"}; + int32_t tokenSize, entrySize; + AuthCacheEntry *pEntry = NULL; + + DbgTrace(1, "-CreateSessionTokenCacheEntry- Start\n", 0); + + if (status == CASA_STATUS_SUCCESS) + { + tokenSize = (uint32_t)strlen(pToken); + } + else + { + tokenSize = 0; + } + + entrySize = tokenSize + sizeof(AuthCacheEntry); + + // Allocate space for the entry + // The AuthCacheEntry structure contains room for the tokens NULL terminator + pEntry = (AuthCacheEntry*) malloc(entrySize); + if (pEntry) + { + // Set the status + pEntry->status = status; + + if (pEntry->status == CASA_STATUS_SUCCESS) + { + memcpy(&pEntry->token[0], pToken, tokenSize); + } + + pEntry->token[tokenSize] = '\0'; + + // Set the time when the entry was added to the cache + pEntry->creationTime = GetTickCount(); + + // First determine the time when the entry is due to expire + if (entryLifetime != 0) + { + pEntry->expirationTime = pEntry->creationTime + (entryLifetime * 1000); + pEntry->doesNotExpire = false; + } + else + { + // The entry does not expire + pEntry->expirationTime = 0; + pEntry->doesNotExpire = true; + } + + retStatus = miCASAWriteBinaryKey(g_hCASAContext, + 0, + &sessionKeyChain, + &sharedId, + (SS_UTF8_T*) pCacheKey, + (uint32_t) strlen(pCacheKey) + 1, + (uint8_t *) pEntry, + (uint32_t*) &entrySize, + NULL, + (SSCS_EXT_T*) pCredStoreScope); + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-CreateSessionTokenCacheEntry- End, pEntry = %0lX\n", (long) pEntry); + + return pEntry; +} + + +//++======================================================================= +void +FreeAuthCacheEntry( + IN AuthCacheEntry *pEntry + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-FreeAuthCacheEntry- Start, pEntry = %0lX\n", (long) pEntry); + + // Free the entry + free(pEntry); + + DbgTrace(1, "-FreeAuthCacheEntry- End\n", 0); +} + + +//++======================================================================= +static +bool +CacheEntryLifetimeExpired( + IN DWORD creationTime, + IN DWORD expirationTime + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DWORD currentTime = GetTickCount(); + bool expired = false; + + DbgTrace(2, "-CacheEntryLifetimeExpired- Start\n", 0); + + // Check if the clock has wrapped + if (currentTime >= creationTime) + { + // The clock has not wrapped, check if the + // expiration time has wrapped. + if (expirationTime > creationTime) + { + // The expiration time also has not wrapped, + // do a straight compare against the current + // time. + if (currentTime >= expirationTime) + { + // It has expired + expired = true; + } + } + } + else + { + // The clock has wrapped, check if the expiration + // time also wrapped. + if (expirationTime > creationTime) + { + // The expiration time did not wrap, therefore + // it has been exceeded since the clock wrapped. + expired = true; + } + else + { + // The expiration time also wrapped, do a straight + // compare against the current time. + if (currentTime >= expirationTime) + { + // It has expired + expired = true; + } + } + } + + DbgTrace(2, "-CacheEntryLifetimeExpired- End, result = %08X\n", expired); + + return expired; +} + + +//++======================================================================= +AuthCacheEntry* +FindSessionTokenEntryInCache( + IN const char *pCacheKey, + IN void *pCredStoreScope + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"}; + SSCS_SECRET_ID_T sharedId = {20, "CASA_SESSION_TOKENS"}; + int32_t valueLength, bytesRequired; + AuthCacheEntry *pEntry = NULL; + + + DbgTrace(1, "-FindSessionTokenEntryInCache- Start\n", 0); + + valueLength = 0; + bytesRequired = 0; + + retStatus = miCASAReadBinaryKey(g_hCASAContext, + 0, + &sessionKeyChain, + &sharedId, + (SS_UTF8_T*) pCacheKey, + (uint32_t) strlen(pCacheKey) + 1, + NULL, + (uint32_t*) &valueLength, + (SSCS_PASSWORD_T*) NULL, + (uint32_t*) &bytesRequired, + (SSCS_EXT_T*) pCredStoreScope); + + if (retStatus == NSSCS_E_ENUM_BUFF_TOO_SHORT + && bytesRequired != 0) + { + pEntry = (AuthCacheEntry*) malloc(bytesRequired); + + if (pEntry) + { + valueLength = bytesRequired; + bytesRequired = 0; + + retStatus = miCASAReadBinaryKey(g_hCASAContext, + 0, + &sessionKeyChain, + &sharedId, + (SS_UTF8_T*) pCacheKey, + (uint32_t) strlen(pCacheKey) + 1, + (uint8_t *) pEntry, + (uint32_t*) &valueLength, + (SSCS_PASSWORD_T*) NULL, + (uint32_t*) &bytesRequired, + (SSCS_EXT_T*) pCredStoreScope); + if (CASA_SUCCESS(retStatus)) + { + if (pEntry->doesNotExpire == false + && CacheEntryLifetimeExpired(pEntry->creationTime, pEntry->expirationTime)) + { + // Remove the entry ??? + //miCASARemoveBinaryKey(); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + + if (!CASA_SUCCESS(retStatus)) + { + FreeAuthCacheEntry(pEntry); + pEntry = NULL; + } + } + } + + DbgTrace(1, "-FindSessionTokenEntryInCache- End, pEntry = %0lX\n", (long) pEntry); + + return pEntry; +} + +//++======================================================================= +AuthCacheEntry* +FindAuthTokenEntryInCache( + IN const char *pCacheKey, + IN const char *pGroupOrHostName, + IN void *pCredStoreScope + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + SSCS_KEYCHAIN_ID_T sessionKeyChain = {26, "SSCS_SESSION_KEY_CHAIN_ID"}; + SSCS_SECRET_ID_T sharedId = {27, "CASA_AUTHENTICATION_TOKENS"}; + int32_t valueLength, bytesRequired, keySize; + AuthCacheEntry *pEntry = NULL; + char *pKey; + + + DbgTrace(1, "-FindAuthTokenEntryInCache- Start\n", 0); + + keySize = (uint32_t)strlen(pCacheKey) + (uint32_t)strlen(pGroupOrHostName) + 2; + + pKey = malloc(keySize); + if (pKey) + { + strncpy(pKey, pCacheKey, keySize); + strncat(pKey, "@", keySize); + strncat(pKey, pGroupOrHostName, keySize); + + valueLength = 0; + bytesRequired = 0; + + retStatus = miCASAReadBinaryKey(g_hCASAContext, + 0, + &sessionKeyChain, + &sharedId, + (SS_UTF8_T*) pKey, + keySize, + NULL, + (uint32_t*) &valueLength, + (SSCS_PASSWORD_T*) NULL, + (uint32_t*) &bytesRequired, + (SSCS_EXT_T*) pCredStoreScope); + + if (retStatus == NSSCS_E_ENUM_BUFF_TOO_SHORT + && bytesRequired != 0) + { + pEntry = (AuthCacheEntry*) malloc(bytesRequired); + + if (pEntry) + { + valueLength = bytesRequired; + bytesRequired = 0; + + retStatus = miCASAReadBinaryKey(g_hCASAContext, + 0, + &sessionKeyChain, + &sharedId, + (SS_UTF8_T*) pKey, + keySize, + (uint8_t *) pEntry, + (uint32_t*) &valueLength, + (SSCS_PASSWORD_T*) NULL, + (uint32_t*) &bytesRequired, + (SSCS_EXT_T*) pCredStoreScope); + if (CASA_SUCCESS(retStatus)) + { + if (pEntry->doesNotExpire == false + && CacheEntryLifetimeExpired(pEntry->creationTime, pEntry->expirationTime)) + { + // Remove the entry ??? + //miCASARemoveBinaryKey(); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + + if (!CASA_SUCCESS(retStatus)) + { + FreeAuthCacheEntry(pEntry); + pEntry = NULL; + } + } + } + + free(pKey); + } + + DbgTrace(1, "-FindAuthTokenEntryInCache- End, pEntry = %0lX\n", (long) pEntry); + + return pEntry; +} + + +//++======================================================================= +CasaStatus +InitializeAuthCache() +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + SSCS_SECRETSTORE_T ssId; + + DbgTrace(1, "-InitializeAuthCache- Start\n", 0); + + ssId.version = NSSCS_VERSION_NUMBER; + strcpy((char *)ssId.ssName, (char *)SSCS_DEFAULT_SECRETSTORE_ID); + + g_hCASAContext = miCASAOpenSecretStoreCache(&ssId, + 0, + NULL); + if (!g_hCASAContext) + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + else + { + retStatus = CASA_STATUS_SUCCESS; + } + + DbgTrace(1, "-InitializeAuthCache- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/client.conf b/CASA-auth-token/client/core/client.conf new file mode 100644 index 00000000..46c0d85f --- /dev/null +++ b/CASA-auth-token/client/core/client.conf @@ -0,0 +1,88 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for client. # +# # +####################################################### + +# +# ATS-hostname setting. +# +# Description: Used to configure the address of the +# ATS that should be used for obtaining +# authentication tokens. +# +# If this parameter is not set, the client +# assummes that the ATS resides in the same +# host as the authentication token consuming +# services. +# +#ATS-hostname hostname or IP address + +# +# ATS-port setting. +# +# Description: Used to configure the port utilized by the +# ATS to listen for connections. +# +# If this parameter is not set .... +# +#ATS-port 2645 + +# +# DisableSecureConnections setting. +# +# Description: Used to disable the use of secure connections (SSL) between +# the Client and ATSs. +# +# If this parameter is not set to true, the client +# defaults to communicating securedly with ATSs. +# +# Security Note: Disabling secure connections allows +# malicious users/processes to view confidential +# information such as username/passwords and to tamper +# with client-ATS communications without being detected. +# You should not disable secure connections unless you are +# trying to debug the authentication token infrastructure. +# +#DisableSecureConnections false + +# +# AllowInvalidCerts setting. +# +# Description: Used to specify that the client should ignore +# invalid certificates presented by ATSs when +# performing SSL communications. +# +# If this parameter is not set to true, the client defaults +# to not ignoring invalid certificates presented by ATSs. +# ATSs. +# +# Security Note: Ignoring invalid certificates downgrades the +# security of your infrastructure by allowing a malicious +# process to impersonate an ATS and obtain information that +# is confidential such as username and passwords. +# +AllowInvalidCerts true + +# +# UsersCannotAllowInvalidCerts setting. +# +# Description: Used to specify that the client should not allow users to +# decide that invalid certificates presented by ATSs should be +# ignored. +# +# If this parameter is not set to true, the client defaults +# to allow users to choose whether or not invalid certificates +# presented by ATSs. +# +# If this parameter is set to true then users are not consulted +# when an invalid server certificate is received and communications +# between the client and the ATS fail. +# +# Note: This parameter has no effect if the setting AllowInvalidCerts +# is set to true. +# +# THIS FUNCTIONALITY HAS NOT BEEN IMPLEMENTED +# +#UsersCannotAllowInvalidCerts true diff --git a/CASA-auth-token/client/core/config.c b/CASA-auth-token/client/core/config.c new file mode 100644 index 00000000..f3680313 --- /dev/null +++ b/CASA-auth-token/client/core/config.c @@ -0,0 +1,686 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Config Key object +// +typedef struct _ConfigKey +{ + LIST_ENTRY listEntry; + char *pKeyName; + int keyNameLen; + char *pValue; + int valueLen; + +} ConfigKey, *pConfigKey; + +// +// Config Interface instance data +// +typedef struct _ConfigIfInstance +{ + LIST_ENTRY listEntry; + int refCount; + char *pConfigFolder; + int configFolderLen; + char *pConfigName; + int configNameLen; + LIST_ENTRY configKeyListHead; + ConfigIf configIf; + +} ConfigIfInstance, *PConfigIfInstance; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// ConfigIf variables +static +LIST_ENTRY g_configIfListHead = {&g_configIfListHead, &g_configIfListHead}; + +static +int g_numConfigIfObjs = 0; + + +//++======================================================================= +static void +RemoveWhiteSpaceFromTheEnd( + IN const char *pInString) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pLineEnd = (char*) pInString + strlen(pInString) - 1; + + + DbgTrace(3, "-RemoveWhiteSpaceFromTheEnd- Start\n", 0); + + while (pLineEnd != pInString) + { + if (*pLineEnd == '\n' + || *pLineEnd == ' ' + || *pLineEnd == '\t') + { + // Strike this character + *pLineEnd = '\0'; + pLineEnd --; + } + else + { + // Found a non-white character + break; + } + } + + DbgTrace(3, "-RemoveWhiteSpaceFromTheEnd- End\n", 0); +} + + +//++======================================================================= +static char* +SkipWhiteSpace( + IN const char *pInString) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pOutString = (char*) pInString; + + DbgTrace(3, "-SkipWhiteSpace- Start\n", 0); + + while (*pOutString != '\0') + { + if (*pOutString == '\n' + || *pOutString == ' ' + || *pOutString == '\t') + { + // Skip this character + pOutString ++; + } + else + { + // Found a non-white character + break; + } + } + + DbgTrace(3, "-SkipWhiteSpace- End\n", 0); + + return pOutString; +} + + +//++======================================================================= +static char* +SkipNonWhiteSpace( + IN const char *pInString) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pOutString = (char*) pInString; + + DbgTrace(3, "-SkipNonWhiteSpace- Start\n", 0); + + while (*pOutString != '\0') + { + if (*pOutString == '\n' + || *pOutString == ' ' + || *pOutString == '\t') + { + // Found a white character + break; + } + else + { + // Skip this character + pOutString ++; + } + } + + DbgTrace(3, "-SkipNonWhiteSpace- End\n", 0); + + return pOutString; +} + + +//++======================================================================= +static void +LowerCaseString( + IN char *pDestString, + IN const char *pSrcString) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int i; + + DbgTrace(3, "-LowerCaseString- Start\n", 0); + + // Copy the string as lower case + for (i = 0; pSrcString[i] != '\0'; i++) + { + if (isalpha(pSrcString[i])) + pDestString[i] = tolower(pSrcString[i]); + else + pDestString[i] = pSrcString[i]; + } + + // Null terminate the destination string + pDestString[i] = '\0'; + + DbgTrace(3, "-LowerCaseString- End\n", 0); +} + + +//++======================================================================= +int SSCS_CALL +ConfigIf_AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); + + DbgTrace(2, "-ConfigIf_AddReference- Start\n", 0); + + // Increment the reference count on the object + pConfigIfInstance->refCount ++; + refCount = pConfigIfInstance->refCount; + + DbgTrace(2, "-ConfigIf_AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +void SSCS_CALL +ConfigIf_ReleaseReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Nothing. +// +// Description: +// Decreases interface reference count. The interface is deallocated if +// the reference count becomes zero. +// +// L2 +//=======================================================================-- +{ + bool freeObj = false; + ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); + + DbgTrace(2, "-ConfigIf_ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + pConfigIfInstance->refCount --; + if (pConfigIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numConfigIfObjs --; + RemoveEntryList(&pConfigIfInstance->listEntry); + } + + // Free object if necessary + if (freeObj) + { + // Free all of the config key objects associated with this configuration + // interface instance. + while (!IsListEmpty(&pConfigIfInstance->configKeyListHead)) + { + LIST_ENTRY *pListEntry; + ConfigKey *pConfigKey; + + // Get reference to entry at the head of the list + pListEntry = pConfigIfInstance->configKeyListHead.Flink; + pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry); + + // Free the buffers associated with the ConfigKey + free(pConfigKey->pKeyName); + free(pConfigKey->pValue); + + // Remove the entry from the list + RemoveEntryList(&pConfigKey->listEntry); + + // Finish freeing the ConfigKey + free(pConfigKey); + } + + // Free the rest of the buffers associated with the interface instance data + free(pConfigIfInstance->pConfigFolder); + free(pConfigIfInstance->pConfigName); + free(pConfigIfInstance); + } + + DbgTrace(2, "-ConfigIf_ReleaseReference- End\n", 0); +} + + +//++======================================================================= +char* SSCS_CALL +ConfigIf_GetEntryValue( + IN const void *pIfInstance, + IN const char *pKeyName) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pKeyName - +// Pointer to NULL terminated string that contains the +// name of the key whose value is being requested. +// +// Returns: +// Pointer to NULL terminated string with value being requested or NULL. +// +// Description: +// Gets value associated with a key for the configuration object. +// +// L2 +//=======================================================================-- +{ + ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); + char *pValue = NULL; + LIST_ENTRY *pListEntry; + ConfigKey *pConfigKey; + int keyNameLen = (int) strlen(pKeyName); + char *pKeyNameLowercase; + + DbgTrace(2, "-ConfigIf_GetEntryValue- Start\n", 0); + + // Allocate enough space to hold lower case version of the key name + pKeyNameLowercase = (char*) malloc(keyNameLen + 1); + if (pKeyNameLowercase) + { + // Lower case the key name + LowerCaseString(pKeyNameLowercase, pKeyName); + + // Try to find matching ConfigKey + pListEntry = pConfigIfInstance->configKeyListHead.Flink; + while (pListEntry != &pConfigIfInstance->configKeyListHead) + { + // Get pointer to the current entry + pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry); + + // Check if we have a match + if (pConfigKey->keyNameLen == keyNameLen + && memcmp(pKeyNameLowercase, pConfigKey->pKeyName, keyNameLen) == 0) + { + // We found it, return its value. + pValue = (char*) malloc(pConfigKey->valueLen + 1); + if (pValue) + { + strcpy(pValue, pConfigKey->pValue); + } + else + { + DbgTrace(0, "-ConfigIf_GetEntryValue- Buffer allocation failure\n", 0); + } + break; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Free the lower case version of the key name + free(pKeyNameLowercase); + } + else + { + DbgTrace(0, "-ConfigIf_GetEntryValue- Buffer allocation failure\n", 0); + } + + DbgTrace(2, "-ConfigIf_GetEntryValue- End, pValue = %08X\n", (unsigned int) pValue); + + return pValue; +} + + + +//++======================================================================= +CasaStatus +GetConfigInterface( + IN const char *pConfigFolder, + IN const char *pConfigName, + INOUT ConfigIf **ppConfigIf) +// +// Arguments: +// pConfigFolder - +// Pointer to NULL terminated string that contains the name of +// the folder containing the configuration file. +// +// pConfigName - +// Pointer to NULL terminated string containing the name of the +// configuration entry. +// +// ppConfigIf - +// Pointer to variable that will receive pointer to ConfigIf +// instance. +// +// Returns: +// Casa Status +// +// Description: +// Get configuration interface to specified configuration entry. +// +// L2 +//=======================================================================-- +{ + int configFolderLen = (int) strlen(pConfigFolder); + int configNameLen = (int)strlen(pConfigName); + ConfigIfInstance *pConfigIfInstance; + LIST_ENTRY *pListEntry; + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_OBJECT_NOT_FOUND); + + DbgTrace(2, "-GetConfigInterface- Start\n", 0); + + // Check if we already have an entry in our list for the configuration + pListEntry = g_configIfListHead.Flink; + while (pListEntry != &g_configIfListHead) + { + // Get pointer to the current entry + pConfigIfInstance = CONTAINING_RECORD(pListEntry, ConfigIfInstance, listEntry); + + // Check if we have a match + if (pConfigIfInstance->configFolderLen == configFolderLen + && pConfigIfInstance->configNameLen == configNameLen + && memcmp(pConfigFolder, pConfigIfInstance->pConfigFolder, configFolderLen) == 0 + && memcmp(pConfigName, pConfigIfInstance->pConfigName, configNameLen) == 0) + { + // We found it, return the ConfigIf associated with the instance data + // after incrementing its reference count. + pConfigIfInstance->refCount ++; + *ppConfigIf = &pConfigIfInstance->configIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + break; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Proceed to create interface instance data for the configuration if none was found + if (retStatus != CASA_STATUS_SUCCESS) + { + char *pFilePath; + + // Build a string containing the configuration file path + pFilePath = (char*) malloc(configFolderLen + 1 + configNameLen + sizeof(".conf")); + if (pFilePath) + { + FILE *pConfigFile; + + strcpy(pFilePath, pConfigFolder); + strcat(pFilePath, pathCharString); + strcat(pFilePath, pConfigName); + strcat(pFilePath, ".conf"); + + // Open the configuration file for reading + pConfigFile = fopen(pFilePath, "r"); + if (pConfigFile) + { + // Opened the file, create a ConfigIfInstance object for it. + pConfigIfInstance = (ConfigIfInstance*) malloc(sizeof(*pConfigIfInstance)); + if (pConfigIfInstance) + { + // Initialize the list head within the instance data + InitializeListHead(&pConfigIfInstance->configKeyListHead); + + // Initialize the ConfigIf within the instance data + pConfigIfInstance->configIf.addReference = ConfigIf_AddReference; + pConfigIfInstance->configIf.releaseReference = ConfigIf_ReleaseReference; + pConfigIfInstance->configIf.getEntryValue = ConfigIf_GetEntryValue; + + // Save the ConfigFolder and ConfigName information within the instance data + pConfigIfInstance->pConfigFolder = (char*) malloc(configFolderLen + 1); + if (pConfigIfInstance->pConfigFolder) + { + strcpy(pConfigIfInstance->pConfigFolder, pConfigFolder); + pConfigIfInstance->configFolderLen = configFolderLen; + + pConfigIfInstance->pConfigName = (char*) malloc(configNameLen + 1); + if (pConfigIfInstance->pConfigName) + { + strcpy(pConfigIfInstance->pConfigName, pConfigName); + pConfigIfInstance->configNameLen = configNameLen; + + // Add the instance data into our list and bump up its reference count + // since we did that. + InsertTailList(&g_configIfListHead, &pConfigIfInstance->listEntry); + pConfigIfInstance->refCount = 1; + + // At this point we want to return success to the caller even if we + // experience a read error. + retStatus = CASA_STATUS_SUCCESS; + + // Return the ConfigIf associated with the instance data after + // incrementing its reference count. + pConfigIfInstance->refCount ++; + *ppConfigIf = &pConfigIfInstance->configIf; + + // Now update the instance data with the information present in the file + if (fseek(pConfigFile, 0, SEEK_SET) == 0) + { + char line[512]; + + while (fgets(line, sizeof(line), pConfigFile) != NULL) + { + int lineLength; + + RemoveWhiteSpaceFromTheEnd(line); + + lineLength = (int) strlen(line); + if (lineLength != 0) + { + char *pKey; + char *pKeyEnd; + char *pValue; + ConfigKey *pConfigKey; + + // Attempt to find the key + pKey = SkipWhiteSpace(line); + + // Make sure that we are not dealing with an empty line or a comment + if (*pKey == '\0' || *pKey == '#') + continue; + + // Go past the key + pKeyEnd = SkipNonWhiteSpace(pKey); + + // Protect against a malformed line + if (*pKeyEnd == '\0') + { + DbgTrace(0, "-GetConfigInterface- Key found without value\n", 0); + continue; + } + + // Attempt to find the value + pValue = SkipWhiteSpace(pKeyEnd); + + // Protect against a malformed line + if (*pValue == '\0') + { + DbgTrace(0, "-GetConfigInterface- Key found without value\n", 0); + continue; + } + + // Delineate the key + *pKeyEnd = '\0'; + + // Create a ConfigKey object for this key/value pair + pConfigKey = (ConfigKey*) malloc(sizeof(*pConfigKey)); + if (pConfigKey) + { + pConfigKey->keyNameLen = (int) strlen(pKey); + pConfigKey->pKeyName = (char*) malloc(pConfigKey->keyNameLen + 1); + if (pConfigKey->pKeyName) + { + // Save the key name in lower case + LowerCaseString(pConfigKey->pKeyName, pKey); + + pConfigKey->valueLen = (int) strlen(pValue); + pConfigKey->pValue = (char*) malloc(pConfigKey->valueLen + 1); + if (pConfigKey->pValue) + { + strcpy(pConfigKey->pValue, pValue); + + // The entry is ready, now associate it with the instance data. + InsertTailList(&pConfigIfInstance->configKeyListHead, &pConfigKey->listEntry); + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + free(pConfigKey->pKeyName); + free(pConfigKey); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + free(pConfigKey); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + } + } + } + } + else + { + DbgTrace(0, "-GetConfigInterface- File seek error, errno = %d\n", errno); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + + // Free the buffers associated with the instance data + free(pConfigIfInstance->pConfigFolder); + free(pConfigIfInstance); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + + // Free the buffer allocated for the instance data + free(pConfigIfInstance); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + } + + // Close the file + fclose(pConfigFile); + } + else + { + DbgTrace(0, "-GetConfigInterface- Unable to open config file, errno = %d\n", errno); + DbgTrace(0, "-GetConfigInterface- Config file unable to open = %s\n", pFilePath); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation error\n", 0); + } + } + + DbgTrace(2, "-GetConfigInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/config_if.h b/CASA-auth-token/client/core/config_if.h new file mode 100644 index 00000000..0cdf31ce --- /dev/null +++ b/CASA-auth-token/client/core/config_if.h @@ -0,0 +1,120 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +#ifndef _CONFIG_IF_H_ +#define _CONFIG_IF_H_ + + +//===[ Include files ]===================================================== + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +/************************************************************************** +*************************************************************************** +** ** +** Configuration Object Interface Definitions ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +typedef +int +(SSCS_CALL *PFNConfiglIf_AddReference)( + IN const void *pIfInstance); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +//=======================================================================-- + + +//++======================================================================= +typedef +void +(SSCS_CALL *PFNConfiglIf_ReleaseReference)( + IN const void *pIfInstance); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Nothing. +// +// Description: +// Decreases interface reference count. The interface is deallocated if +// the reference count becomes zero. +//=======================================================================-- + + +//++======================================================================= +typedef +char* +(SSCS_CALL *PFNConfiglIf_GetEntryValue)( + IN const void *pIfInstance, + IN const char *pKeyName); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pKeyName - +// Pointer to NULL terminated string that contains the +// name of the key whose value is being requested. +// +// Returns: +// Pointer to NULL terminated string with value being requested or NULL. +// +// Description: +// Gets value associated with a key for the configuration object. +//=======================================================================-- + + +// +// Config Interface Object +// +typedef struct _ConfigIf +{ + PFNConfiglIf_AddReference addReference; + PFNConfiglIf_ReleaseReference releaseReference; + PFNConfiglIf_GetEntryValue getEntryValue; + +} ConfigIf, *PConfigIf; + + +#endif // #ifndef _CONFIG_IF_H_ + diff --git a/CASA-auth-token/client/core/engine.c b/CASA-auth-token/client/core/engine.c new file mode 100644 index 00000000..a697f712 --- /dev/null +++ b/CASA-auth-token/client/core/engine.c @@ -0,0 +1,894 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +#define DEFAULT_RETRY_LIFETIME 5 // seconds + +//===[ Function prototypes ]=============================================== + +int +InitializeLibrary(void); + +//===[ Global variables ]================================================== + +// +// Debug tracing level +// +int DebugLevel = 0; + +// +// Operating parameter +// +bool g_bInitialized = false; +long g_rpcFlags = SECURE_RPC_FLAG | ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG; +char *g_pATSHostName = NULL; +uint16_t g_ATSPort = 2645; + + +//++======================================================================= +static +CasaStatus +ObtainSessionToken( + IN RpcSession *pRpcSession, + IN AuthPolicy *pAuthPolicy, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char **ppSessionToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + LIST_ENTRY *pListEntry; + AuthCacheEntry *pCacheEntry = NULL; + + DbgTrace(1, "-ObtainSessionToken- Start\n", 0); + + // Initialize output parameter + *ppSessionToken = NULL; + + // Look in our cache for an entry that matches one of the auth + // contexts specified in the AuthPolicy object. + pListEntry = pAuthPolicy->authContextListHead.Flink; + while (pListEntry != &pAuthPolicy->authContextListHead) + { + AuthContext *pAuthContext; + + // Get pointer to AuthContext structure + pAuthContext = CONTAINING_RECORD(pListEntry, AuthContext, listEntry); + + // Try to find a cache entry for the auth context + pCacheEntry = FindSessionTokenEntryInCache(pAuthContext->pContext, + pCredStoreScope); + if (pCacheEntry != NULL) + { + // Cache entry found, check if it is of use to us. + if (CASA_SUCCESS(pCacheEntry->status)) + { + // This entry can be used, stop looking. + retStatus = pCacheEntry->status; + break; + } + else + { + // Free the entry + FreeAuthCacheEntry(pCacheEntry); + } + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // If we did not find a cache entry that we can use, then try to create one. + pListEntry = pAuthPolicy->authContextListHead.Flink; + while (!CASA_SUCCESS(retStatus) + && pListEntry != &pAuthPolicy->authContextListHead) + { + AuthContext *pAuthContext; + char *pAuthMechToken; + + // Get pointer to AuthContext structure + pAuthContext = CONTAINING_RECORD(pListEntry, AuthContext, listEntry); + + // Only try to create cache entry for the auth context if there is not + // one already. + pCacheEntry = FindSessionTokenEntryInCache(pAuthContext->pContext, + pCredStoreScope); + if (pCacheEntry == NULL) + { + char *pReqMsg = NULL; + char *pRespMsg = NULL; + int respLen; + + // Get authentication mechanism token + retStatus = GetAuthMechToken(pAuthContext, + pHostName, + pCredStoreScope, + &pAuthMechToken); + if (!CASA_SUCCESS(retStatus)) + { + // We were not able to obtain an authentication mechanism token + // for the context. + // + // Advance to the next entry + pListEntry = pListEntry->Flink; + continue; + } + + // Authenticate to the ATS + pReqMsg = BuildAuthenticateMsg(pAuthContext, pAuthMechToken); + if (pReqMsg) + { + // Issue rpc + retStatus = Rpc(pRpcSession, + "Authenticate", + g_rpcFlags, + pReqMsg, + &pRespMsg, + &respLen); + if (CASA_SUCCESS(retStatus)) + { + AuthenticateResp *pAuthenticateResp; + + // Create Authenticate response object + retStatus = CreateAuthenticateResp(pRespMsg, respLen, &pAuthenticateResp); + if (CASA_SUCCESS(retStatus)) + { + // Return the auth token to the caller + pCacheEntry = CreateSessionTokenCacheEntry(pAuthContext->pContext, + retStatus, + pAuthenticateResp->pToken, + pAuthenticateResp->tokenLifetime, + pCredStoreScope); + + pAuthenticateResp->pToken = NULL; // To keep us from freeing the buffer + + // Free the Authenticate response object + RelAuthenticateResp(pAuthenticateResp); + } + } + else + { + DbgTrace(0, "-ObtainSessionToken- Authenticate Rpc failure, error = %08X\n", retStatus); + } + + // Free resources that may be hanging around + if (pRespMsg) + free(pRespMsg); + + free(pReqMsg); + } + else + { + DbgTrace(0, "-ObtainSessionToken- Error building Authenticate msg\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Add the entry to the cache if successful or if the reason that we failed + // was because the server was unavailable. + if (CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE) + { + pCacheEntry = CreateSessionTokenCacheEntry(pAuthContext->pContext, + retStatus, + NULL, + DEFAULT_RETRY_LIFETIME, + pCredStoreScope); + + } + + // Release the cache entry if the resulting status is not successful + if (!CASA_SUCCESS(retStatus)) + { + FreeAuthCacheEntry(pCacheEntry); + } + + // Free up the buffer associated with the authentication mechanism token + free(pAuthMechToken); + } + else + { + // Free the entry + FreeAuthCacheEntry(pCacheEntry); + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Return session token if successful + if (CASA_SUCCESS(retStatus)) + { + // Allocate a buffer for the return token + *ppSessionToken = (char*) malloc(strlen(pCacheEntry->token) + 1); + if (*ppSessionToken) + { + // Copy the token onto the allocated buffer + strcpy(*ppSessionToken, pCacheEntry->token); + } + else + { + DbgTrace(0, "-ObtainSessionToken- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + FreeAuthCacheEntry(pCacheEntry); + } + + DbgTrace(1, "-ObtainSessionToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus +ObtainAuthTokenFromServer( + IN const char *pServiceName, + IN const char *pHostName, + INOUT char **ppAuthToken, + INOUT int *pTokenLifetime, + IN void *pCredStoreScope) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + RpcSession *pRpcSession; + + DbgTrace(1, "-ObtainAuthTokenFromServer- Start\n", 0); + + // Initialize output parameter + *ppAuthToken = NULL; + + // Open Rpc Session to the auth service at the specified host + pRpcSession = OpenRpcSession((g_pATSHostName != NULL) ? g_pATSHostName : pHostName, + g_ATSPort); + if (pRpcSession) + { + char *pReqMsg = NULL; + char *pRespMsg = NULL; + int respLen; + AuthPolicy *pAuthPolicy = NULL; + GetAuthPolicyResp *pGetAuthPolicyResp = NULL; + GetAuthTokenResp *pGetAuthTokenResp = NULL; + char *pSessionToken = NULL; + + // Request the auth parameters associated with this service + pReqMsg = BuildGetAuthPolicyMsg(pServiceName, "localhost"); // tbd - This will be changed in the future so that we can support services residing in a different host than the ATS + if (pReqMsg) + { + // Issue rpc + retStatus = Rpc(pRpcSession, + "GetAuthPolicy", + g_rpcFlags, + pReqMsg, + &pRespMsg, + &respLen); + if (CASA_SUCCESS(retStatus)) + { + // Create GetAuthPolicy response object + retStatus = CreateGetAuthPolicyResp(pRespMsg, respLen, &pGetAuthPolicyResp); + if (CASA_SUCCESS(retStatus)) + { + // Create the AuthPolicy object + retStatus = CreateAuthPolicy(pGetAuthPolicyResp->pPolicy, + pGetAuthPolicyResp->policyLen, + &pAuthPolicy); + if (CASA_SUCCESS(retStatus)) + { + // Now try to obtain a session token + retStatus = ObtainSessionToken(pRpcSession, + pAuthPolicy, + (g_pATSHostName != NULL) ? g_pATSHostName : pHostName, + pCredStoreScope, + &pSessionToken); + if (CASA_SUCCESS(retStatus)) + { + // Request auth token for the service + free(pReqMsg); + pReqMsg = BuildGetAuthTokenMsg(pServiceName, "localhost", pSessionToken); // tbd - This will be changed in the future so that we can support services residing in a different host than the ATS + if (pReqMsg) + { + // Free the previous response msg buffer + free(pRespMsg); + pRespMsg = NULL; + + // Issue rpc + retStatus = Rpc(pRpcSession, + "GetAuthToken", + g_rpcFlags, + pReqMsg, + &pRespMsg, + &respLen); + if (CASA_SUCCESS(retStatus)) + { + // Create GetAuthPolicy response object + retStatus = CreateGetAuthTokenResp(pRespMsg, respLen, &pGetAuthTokenResp); + if (CASA_SUCCESS(retStatus)) + { + // Return the auth token to the caller + *ppAuthToken = pGetAuthTokenResp->pToken; + pGetAuthTokenResp->pToken = NULL; // To keep us from freeing the buffer + *pTokenLifetime = pGetAuthTokenResp->tokenLifetime; + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Failed to create GetAuthTokenResp object, error = %08X\n", retStatus); + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- GetAuthToken Rpc failure, error = %08X\n", retStatus); + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Error building GetAuthToken msg\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Failed to obtain session token, error = %08X\n", retStatus); + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Failed to create AuthPolicy object, error = %08X\n", retStatus); + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Failed to create GetAuthPolicyResp object, error = %08X\n", retStatus); + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- GetAuthPolicy Rpc failure, error = %08X\n", retStatus); + } + + // Free resources that may be hanging around + if (pReqMsg) + free(pReqMsg); + + if (pRespMsg) + free(pRespMsg); + + if (pSessionToken) + free(pSessionToken); + + if (pGetAuthTokenResp) + RelGetAuthTokenResp(pGetAuthTokenResp); + + if (pGetAuthPolicyResp) + RelGetAuthPolicyResp(pGetAuthPolicyResp); + + if (pAuthPolicy) + RelAuthPolicy(pAuthPolicy); + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Error building GetAuthPolicy msg\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Close the Rpc Session + CloseRpcSession(pRpcSession); + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Error opening Rpc session\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-ObtainAuthTokenFromServer- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +ObtainAuthTokenInt( + IN const char *pServiceName, + IN const char *pHostName, + INOUT char *pAuthTokenBuf, + INOUT int *pAuthTokenBufLen, + IN void *pCredStoreScope) +// +// Arguments: +// pServiceName - +// Pointer to NULL terminated string that contains the +// name of the service to which the client is trying to +// authenticate. +// +// pHostName - +// Pointer to NULL terminated string that contains the +// name of the host where resides the service to which the +// client is trying to authenticate. Note that the name +// can either be a DNS name or a dotted IP address. +// +// pAuthTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pAuthTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pAuthTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pAuthTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pAuthTokenBuf is +// not large enough. +// +// pCredStoreScope - +// Pointer to CASA structure for scoping credential store access +// to specific users. This can only be leveraged by applications +// running in the context of System. + +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified +// service at host. The user is scoped using the info associated +// with the magic cookie. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + AuthCacheEntry *pCacheEntry; + char *pNormalizedHostName; + char *pToken; + HANDLE hUserMutex = NULL; + + DbgTrace(1, "-ObtainAuthTokenInt- Start\n", 0); + + // Verify the input parameters + if (pServiceName == NULL + || pHostName == NULL + || pAuthTokenBufLen == NULL + || (*pAuthTokenBufLen != 0 && pAuthTokenBuf == NULL)) + { + DbgTrace(0, "-ObtainAuthTokenInt- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + DbgTrace(1, "-ObtainAuthTokenInt- ServiceName = %s\n", pServiceName); + DbgTrace(1, "-ObtainAuthTokenInt- HostName = %s\n", pHostName); + DbgTrace(1, "-ObtainAuthTokenInt- BufferLength = %d\n", *pAuthTokenBufLen); + + // Obtain our synchronization mutex + AcquireModuleMutex; + + // Create user synchronization mutex + retStatus = CreateUserMutex(&hUserMutex); + if (retStatus != CASA_STATUS_SUCCESS) + { + DbgTrace(0, "-ObtainAuthTokenInt- Error creating mutex for the user\n", 0); + goto exit; + } + + // Make sure we are fully initialized + if (g_bInitialized == false) + { + retStatus = InitializeLibrary(); + + if (retStatus == CASA_STATUS_SUCCESS) + { + g_bInitialized = true; + } + else + { + goto exit; + } + } + + // Release our synchronization mutex + ReleaseModuleMutex; + + // Normalize the host name + pNormalizedHostName = NormalizeHostName(pHostName); + if (pNormalizedHostName) + { + // Start user process synchronization + AcquireUserMutex(hUserMutex); + + // Try to find a cache entry for the service + pCacheEntry = FindAuthTokenEntryInCache(pServiceName, + pNormalizedHostName, + pCredStoreScope); + if (pCacheEntry == NULL) + { + // Initialize to retry in case of failure + int cacheEntryLifetime = DEFAULT_RETRY_LIFETIME; + + // Cache entry created, now try to obtain auth token from the CASA Server + retStatus = ObtainAuthTokenFromServer(pServiceName, + pNormalizedHostName, + &pToken, + &cacheEntryLifetime, + pCredStoreScope); + + // Add the entry to the cache if successful or if the reason that we failed + // was because the server was un-available. + if (CASA_SUCCESS(retStatus) + || CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE) + { + pCacheEntry = CreateAuthTokenCacheEntry(pServiceName, + pNormalizedHostName, + retStatus, + pToken, + cacheEntryLifetime, + pCredStoreScope); + if (pCacheEntry) + { + // Release the cache entry if the resulting status is not successful + if (!CASA_SUCCESS(retStatus)) + { + FreeAuthCacheEntry(pCacheEntry); + } + } + } + } + else + { + // Cache entry found, update the return status with the information saved in it + // and release it if its status is not successful. + if (!CASA_SUCCESS(retStatus = pCacheEntry->status)) + { + FreeAuthCacheEntry(pCacheEntry); + } + } + + // Try to return auth token if we have one to return + if (CASA_SUCCESS(retStatus)) + { + int tokenLen = (int) strlen(pCacheEntry->token) + 1; + + // We have an authentication token, try to return it to the caller + // after verifying that the supplied buffer is big enough. + if (*pAuthTokenBufLen >= tokenLen) + { + // Return the auth token to the caller + DbgTrace(2, "-ObtainAuthTokenInt- Copying the token into the callers buffer\n", 0); + strcpy(pAuthTokenBuf, pCacheEntry->token); + } + else + { + DbgTrace(0, "-ObtainAuthTokenInt- The supplied buffer is not large enough", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the token length to the caller + *pAuthTokenBufLen = tokenLen; + + FreeAuthCacheEntry(pCacheEntry); + } + + // Stop user process synchronization + ReleaseUserMutex(hUserMutex); + + // Free the space allocated for the normalized host name + free(pNormalizedHostName); + } + else + { + DbgTrace(0, "-ObtainAuthTokenInt- Host name normalization failed\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + +exit: + + if (hUserMutex != NULL) + { + DestroyUserMutex(hUserMutex); + } + DbgTrace(1, "-ObtainAuthTokenInt- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus SSCS_CALL +ObtainAuthToken( + IN const char *pServiceName, + IN const char *pHostName, + INOUT char *pAuthTokenBuf, + INOUT int *pAuthTokenBufLen) +// +// Arguments: +// pServiceName - +// Pointer to NULL terminated string that contains the +// name of the service to which the client is trying to +// authenticate. +// +// pHostName - +// Pointer to NULL terminated string that contains the +// name of the host where resides the service to which the +// client is trying to authenticate. Note that the name +// can either be a DNS name or a dotted IP address. +// +// pAuthTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pAuthTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pAuthTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pAuthTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pAuthTokenBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified +// service at host. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + + DbgTrace(1, "-ObtainAuthToken- Start\n", 0); + + // Call our internal worker + retStatus = ObtainAuthTokenInt(pServiceName, + pHostName, + pAuthTokenBuf, + pAuthTokenBufLen, + NULL); + + DbgTrace(1, "-ObtainAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +InitializeLibrary(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + int getConfigStatus = -1; + ConfigIf *pClientConfigIf; + char *pATSPortSetting; + char *pDisableSecureConnections; + char *pAllowInvalidCerts; + char *pUsersCannotAllowInvalidCerts; + + DbgTrace(1, "-InitializeLibrary- Start\n", 0); + + // Try to obtain client configuration settings + getConfigStatus = GetConfigInterface(clientConfigFolder, + "client", + &pClientConfigIf); + if (CASA_SUCCESS(getConfigStatus) + && CasaStatusCode(getConfigStatus) != CASA_STATUS_OBJECT_NOT_FOUND) + { + // Check if an ATS hostname has been configured + g_pATSHostName = pClientConfigIf->getEntryValue(pClientConfigIf, "ATS-hostname"); + if (g_pATSHostName != NULL) + { + DbgTrace(0, "-InitializeLibrary- ATS hostname configured = %s\n", g_pATSHostName); + } + + // Check if the DisableSecureConnections setting has been configured + pDisableSecureConnections = pClientConfigIf->getEntryValue(pClientConfigIf, "DisableSecureConnections"); + if (pDisableSecureConnections != NULL) + { + DbgTrace(0, "-InitializeLibrary- DisableSecureConnections setting configured = %s\n", pDisableSecureConnections); + + // Adjust the g_rpcFlags variable based on the setting + if (stricmp(pDisableSecureConnections, "true") == 0) + { + g_rpcFlags &= ~SECURE_RPC_FLAG; + + // Change the default ATS port to 80 from 443 + g_ATSPort = 80; + } + else if (stricmp(pDisableSecureConnections, "false") == 0) + { + g_rpcFlags |= SECURE_RPC_FLAG; + } + + // Free the buffer holding the DisableSecureConnections setting + free(pDisableSecureConnections); + } + + // Check the AllowInvalidCerts setting if using secure connections + if (g_rpcFlags & SECURE_RPC_FLAG) + { + // Check if the AllowInvalidCerts setting has been configured + pAllowInvalidCerts = pClientConfigIf->getEntryValue(pClientConfigIf, "AllowInvalidCerts"); + if (pAllowInvalidCerts != NULL) + { + DbgTrace(0, "-InitializeLibrary- AllowInvalidCerts setting configured = %s\n", pAllowInvalidCerts); + + // Adjust the g_rpcFlags variable based on the setting + if (stricmp(pAllowInvalidCerts, "false") == 0) + { + g_rpcFlags &= ~ALLOW_INVALID_CERTS_RPC_FLAG; + } + else if (stricmp(pAllowInvalidCerts, "true") == 0) + { + g_rpcFlags |= ALLOW_INVALID_CERTS_RPC_FLAG; + } + + // Free the buffer holding the AllowInvalidCerts setting + free(pAllowInvalidCerts); + } + + // Check the UsersCannotAllowInvalidCerts setting if not allowing invalid certs. + if ((g_rpcFlags & ALLOW_INVALID_CERTS_RPC_FLAG) == 0) + { + // Check if the UsersCannotAllowInvalidCerts setting has been configured + pUsersCannotAllowInvalidCerts = pClientConfigIf->getEntryValue(pClientConfigIf, "UsersCannotAllowInvalidCerts"); + if (pUsersCannotAllowInvalidCerts != NULL) + { + DbgTrace(0, "-InitializeLibrary- UsersCannotAllowInvalidCerts setting configured = %s\n", pUsersCannotAllowInvalidCerts); + + // Adjust the g_rpcFlags variable based on the setting + if (stricmp(pUsersCannotAllowInvalidCerts, "false") == 0) + { + g_rpcFlags |= ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG; + } + else if (stricmp(pUsersCannotAllowInvalidCerts, "true") == 0) + { + g_rpcFlags &= ~ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG; + } + + // Free the buffer holding the UsersCannotAllowInvalidCerts setting + free(pUsersCannotAllowInvalidCerts); + } + } + } + + // Check if an ATS port number has been configured + pATSPortSetting = pClientConfigIf->getEntryValue(pClientConfigIf, "ATS-port"); + if (pATSPortSetting != NULL) + { + DbgTrace(0, "-InitializeLibrary- ATS port number configured = %s\n", pATSPortSetting); + + // Convert the number to hex + g_ATSPort = (int) dtoul(pATSPortSetting, strlen(pATSPortSetting)); + + // Free the buffer holding the port number + free(pATSPortSetting); + } + + // Release config interface instance + pClientConfigIf->releaseReference(pClientConfigIf); + } + + // Initialize the host name normalization + retStatus = InitializeHostNameNormalization(); + if (CASA_SUCCESS(retStatus)) + { + // Normalize ATS host name if configured + if (g_pATSHostName) + { + char *pNormalizedHostName = NormalizeHostName(g_pATSHostName); + if (pNormalizedHostName) + { + // Use this name instead of the one that we already have + free(g_pATSHostName); + g_pATSHostName = pNormalizedHostName; + } + else + { + DbgTrace(0, "-InitializeLibrary- ATS Hostname normalization failed\n", 0); + } + } + + // Initialize the auth cache + retStatus = InitializeAuthCache(); + if (CASA_SUCCESS(retStatus)) + { + retStatus = InitializeRpc(); + } + else + { + DbgTrace(0, "-InitializeLibrary- Auth cache intialization failed\n", 0); + } + } + else + { + DbgTrace(0, "-InitializeLibrary- HostName Normalizer intialization failed\n", 0); + } + + DbgTrace(1, "-InitializeLibrary- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/getpolicymsg.c b/CASA-auth-token/client/core/getpolicymsg.c new file mode 100644 index 00000000..ccb24738 --- /dev/null +++ b/CASA-auth-token/client/core/getpolicymsg.c @@ -0,0 +1,745 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Parse states +// +#define AWAITING_ROOT_ELEMENT_START 0x0 +#define AWAITING_ROOT_ELEMENT_END 0x1 +#define AWAITING_STATUS_ELEMENT_START 0x2 +#define AWAITING_STATUS_ELEMENT_END 0x3 +#define AWAITING_STATUS_DATA 0x4 +#define AWAITING_DESCRIPTION_ELEMENT_START 0x5 +#define AWAITING_DESCRIPTION_ELEMENT_END 0x6 +#define AWAITING_DESCRIPTION_DATA 0x7 +#define AWAITING_AUTH_TOKEN_ELEMENT_START 0x8 +#define AWAITING_AUTH_TOKEN_ELEMENT_END 0x9 +#define AWAITING_AUTH_TOKEN_DATA 0xA +#define AWAITING_AUTH_POLICY_ELEMENT_START 0xB +#define AWAITING_AUTH_POLICY_ELEMENT_END 0xC +#define AWAITING_AUTH_POLICY_DATA 0xD +#define DONE_PARSING 0xE + +// +// Get Authentication Policy Response Parse Structure +// +typedef struct _GetAuthPolicyRespParse +{ + XML_Parser p; + int state; + int elementDataProcessed; + GetAuthPolicyResp *pGetAuthPolicyResp; + CasaStatus status; + +} GetAuthPolicyRespParse, *PGetAuthPolicyRespParse; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +char* +BuildGetAuthPolicyMsg( + IN const char *pServiceName, + IN const char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pMsg = NULL; + int bufferSize; + + DbgTrace(1, "-BuildGetAuthPolicyMsg- Start\n", 0); + + /* + * The format of the get authentication policy request message is as follows: + * + * + * + * service name<\service> + * host name + * + * + */ + + // Determine the buffer size necessary to hold the msg + bufferSize = strlen(XML_DECLARATION) + + 2 // crlf + + 1 // < + + strlen(GET_AUTH_POLICY_REQUEST_ELEMENT_NAME) + + 3 // >crlf + + 1 // < + + strlen(SERVICE_ELEMENT_NAME) + + 1 // > + + strlen(pServiceName) + + 2 // crlf + + 2 // + + strlen(pHostName) + + 2 // crlf + + 2 // null + + // Allocate the msg buffer + pMsg = (char*) malloc(bufferSize); + if (pMsg) + { + // Now build the message + memset(pMsg, 0, bufferSize); + strcat(pMsg, XML_DECLARATION); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, GET_AUTH_POLICY_REQUEST_ELEMENT_NAME); + strcat(pMsg, ">\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, SERVICE_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pServiceName); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, HOST_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pHostName); + strcat(pMsg, "\r\n"); + strcat(pMsg, ""); + } + else + { + DbgTrace(0, "-BuildGetAuthPolicyMsg- Buffer allocation error\n", 0); + } + + DbgTrace(1, "-BuildGetAuthPolicyMsg- End, pMsg = %0lX\n", (long) pMsg); + + return pMsg; +} + + +//++======================================================================= +static +void XMLCALL +GetAuthPolicyRespStartElementHandler( + IN GetAuthPolicyRespParse *pGetAuthPolicyRespParse, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthPolicyRespStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pGetAuthPolicyRespParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the Get Authentication + // Policy Response Element. + if (strcmp(name, GET_AUTH_POLICY_RESPONSE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthPolicyRespParse->state = AWAITING_STATUS_ELEMENT_START; + } + else + { + DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + case AWAITING_STATUS_ELEMENT_START: + + // In this state, we are only expecting the Status Element. + if (strcmp(name, STATUS_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthPolicyRespParse->state = AWAITING_DESCRIPTION_ELEMENT_START; + } + else + { + DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + case AWAITING_DESCRIPTION_ELEMENT_START: + + // In this state, we are only expecting the Description Element. + if (strcmp(name, DESCRIPTION_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthPolicyRespParse->state = AWAITING_DESCRIPTION_DATA; + } + else + { + DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_POLICY_ELEMENT_START: + + // In this state, we are only expecting the Authentication Policy Element. + if (strcmp(name, AUTH_POLICY_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthPolicyRespParse->state = AWAITING_AUTH_POLICY_DATA; + } + else + { + DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected state = %d\n", pGetAuthPolicyRespParse->state); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-GetAuthPolicyRespStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +ConsumeElementData( + IN GetAuthPolicyRespParse *pGetAuthPolicyRespParse, + IN const XML_Char *s, + IN int len, + INOUT char **ppElementData, + INOUT int *pElementDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + + DbgTrace(3, "-ConsumeElementData- Start\n", 0); + + // Proceed based on whether or not we have already consumed data + // for this element. + if (*ppElementData == NULL) + { + // We have not yet consumed data for this element + pGetAuthPolicyRespParse->elementDataProcessed = len; + + // Allocate a buffer to hold this element data (null terminated). + *ppElementData = (char*) malloc(len + 1); + if (*ppElementData) + { + memset(*ppElementData, 0, len + 1); + memcpy(*ppElementData, s, len); + + // Return the length of the element data buffer + *pElementDataLen = pGetAuthPolicyRespParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + char *pNewBuf; + + // We have already received token data, append this data to it. + pNewBuf = (char*) malloc(pGetAuthPolicyRespParse->elementDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pGetAuthPolicyRespParse->elementDataProcessed + len + 1); + memcpy(pNewBuf, + *ppElementData, + pGetAuthPolicyRespParse->elementDataProcessed); + memcpy(pNewBuf + pGetAuthPolicyRespParse->elementDataProcessed, s, len); + pGetAuthPolicyRespParse->elementDataProcessed += len; + + // Swap the buffers + free(*ppElementData); + *ppElementData = pNewBuf; + + // Return the length of the element data buffer + *pElementDataLen = pGetAuthPolicyRespParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + DbgTrace(3, "-ConsumeElementData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +void XMLCALL +GetAuthPolicyRespCharDataHandler( + IN GetAuthPolicyRespParse *pGetAuthPolicyRespParse, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthPolicyRespCharDataHandler- Start\n", 0); + + // Just exit if being called to process white space + if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') + { + goto exit; + } + + // Proceed based on the state + switch (pGetAuthPolicyRespParse->state) + { + case AWAITING_DESCRIPTION_DATA: + case AWAITING_DESCRIPTION_ELEMENT_END: + + // Ignore the status description data for now. + // tbd + + // Advanced to the next state + pGetAuthPolicyRespParse->state = AWAITING_DESCRIPTION_ELEMENT_END; + break; + + case AWAITING_STATUS_DATA: + + // Set the appropriate status in the AuthenticationResp based on the + // returned status. + if (strncmp(HTTP_OK_STATUS_CODE, s, len) == 0) + { + pGetAuthPolicyRespParse->status = CASA_STATUS_SUCCESS; + } + else if (strncmp(HTTP_UNAUTHORIZED_STATUS_CODE, s, len) == 0) + { + pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_AUTHENTICATION_FAILURE); + } + else if (strncmp(HTTP_NOT_FOUND_STATUS_CODE, s, len) == 0) + { + pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_NOT_CONFIGURED); + } + else if (strncmp(HTTP_SERVER_ERROR_STATUS_CODE, s, len) == 0) + { + pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_SERVER_ERROR); + } + else + { + DbgTrace(0, "-GetAuthPolicyRespCharDataHandler- Un-expected status\n", 0); + pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Advanced to the next state + pGetAuthPolicyRespParse->state = AWAITING_STATUS_ELEMENT_END; + break; + + case AWAITING_AUTH_POLICY_DATA: + case AWAITING_AUTH_POLICY_ELEMENT_END: + + pGetAuthPolicyRespParse->status = ConsumeElementData(pGetAuthPolicyRespParse, + s, + len, + &pGetAuthPolicyRespParse->pGetAuthPolicyResp->pPolicy, + &pGetAuthPolicyRespParse->pGetAuthPolicyResp->policyLen); + if (CASA_SUCCESS(pGetAuthPolicyRespParse->status)) + { + // Advanced to the next state + pGetAuthPolicyRespParse->state = AWAITING_AUTH_POLICY_ELEMENT_END; + } + else + { + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-GetAuthPolicyRespCharDataHandler- Un-expected state = %d\n", pGetAuthPolicyRespParse->state); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-GetAuthPolicyRespCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +GetAuthPolicyRespEndElementHandler( + IN GetAuthPolicyRespParse *pGetAuthPolicyRespParse, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthPolicyRespEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pGetAuthPolicyRespParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the Get Authentication + // Policy Response Element. + if (strcmp(name, GET_AUTH_POLICY_RESPONSE_ELEMENT_NAME) == 0) + { + // Done. + pGetAuthPolicyRespParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-GetAuthPolicyRespEndHandler- Un-expected end element\n", 0); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + case AWAITING_DESCRIPTION_ELEMENT_END: + + // In this state, we are only expecting the Description Element. + if (strcmp(name, DESCRIPTION_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthPolicyRespParse->state = AWAITING_STATUS_DATA; + } + else + { + DbgTrace(0, "-GetAuthPolicyRespEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + case AWAITING_STATUS_ELEMENT_END: + + // In this state, we are only expecting the Status Element. + if (strcmp(name, STATUS_ELEMENT_NAME) == 0) + { + // Good, advance to the next state based on the status code. + if (CASA_SUCCESS(pGetAuthPolicyRespParse->status)) + { + // The request completed successfully + pGetAuthPolicyRespParse->state = AWAITING_AUTH_POLICY_ELEMENT_START; + } + else + { + pGetAuthPolicyRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + } + else + { + DbgTrace(0, "-GetAuthPolicyRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_POLICY_ELEMENT_END: + + // In this state, we are only expecting the Authentication Policy Element. + if (strcmp(name, AUTH_POLICY_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthPolicyRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-GetAuthPolicyRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-GetAuthPolicyRespEndElementHandler- Un-expected state = %d\n", pGetAuthPolicyRespParse->state); + XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-GetAuthPolicyRespEndElementHandler- End\n", 0); +} + + +//++======================================================================= +CasaStatus +CreateGetAuthPolicyResp( + IN char *pRespMsg, + IN int respLen, + INOUT GetAuthPolicyResp **ppGetAuthPolicyResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + GetAuthPolicyRespParse getAuthPolicyRespParse = {0}; + GetAuthPolicyResp *pGetAuthPolicyResp; + + DbgTrace(1, "-CreateGetAuthPolicyResp- Start\n", 0); + + /* + * When a get authentication policy request is processed successfully, the + * server replies to the client with a message with the following format: + * + * + * + * ok200 + * authentication policy data + * + * + * When a get authentication policy request fails to be successfully processed, + * the server responds with an error and an error description string. The message + * format of an unsuccessful reply is as follows: + * + * + * + * status descriptionstatus code + * + * + * Plase note that the protocol utilizes the status codes defined + * in the HTTP 1.1 Specification. + * + */ + + // Allocate GetAuthPolicyResp object + pGetAuthPolicyResp = malloc(sizeof(*pGetAuthPolicyResp)); + if (pGetAuthPolicyResp) + { + XML_Parser p; + + // Initialize the GetAuthPolicyResp object and set it in the + // parse oject. + memset(pGetAuthPolicyResp, 0, sizeof(*pGetAuthPolicyResp)); + getAuthPolicyRespParse.pGetAuthPolicyResp = pGetAuthPolicyResp; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + getAuthPolicyRespParse.p = p; + + // Initialize the status within the parse object + getAuthPolicyRespParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + (XML_StartElementHandler) GetAuthPolicyRespStartElementHandler, + (XML_EndElementHandler) GetAuthPolicyRespEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, (XML_CharacterDataHandler) GetAuthPolicyRespCharDataHandler); + + + // Set our user data + XML_SetUserData(p, &getAuthPolicyRespParse); + + // Parse the document + if (XML_Parse(p, pRespMsg, respLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (getAuthPolicyRespParse.state == DONE_PARSING) + { + // The parse operation succeded, obtain the status returned + // by the server. + retStatus = getAuthPolicyRespParse.status; + } + else + { + DbgTrace(0, "-CreateGetAuthPolicyResp- Parse operation did not complete\n", 0); + + // Check if a status has been recorded + if (getAuthPolicyRespParse.status != CASA_STATUS_SUCCESS) + { + retStatus = getAuthPolicyRespParse.status; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + } + else + { + DbgTrace(0, "-CreateGetAuthPolicyResp- Parse error %d\n", XML_GetErrorCode(p)); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + + // Free the parser + XML_ParserFree(p); + } + else + { + DbgTrace(0, "-CreateGetAuthPolicyResp- Parser creation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Return the AuthenticationResp object to the caller if necessary + if (CASA_SUCCESS(retStatus)) + { + *ppGetAuthPolicyResp = pGetAuthPolicyResp; + } + else + { + free(pGetAuthPolicyResp); + } + } + else + { + DbgTrace(0, "-CreateGetAuthPolicyResp- Memory allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-CreateGetAuthPolicyResp- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +RelGetAuthPolicyResp( + IN GetAuthPolicyResp *pGetAuthPolicyResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-RelGetAuthPolicyResp- Start\n", 0); + + // Free the buffer holding the authentication policy + if (pGetAuthPolicyResp->pPolicy) + free(pGetAuthPolicyResp->pPolicy); + + // Free the GetAuthPolicyResp + free(pGetAuthPolicyResp); + + DbgTrace(1, "-RelGetAuthPolicyResp- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/gettokenmsg.c b/CASA-auth-token/client/core/gettokenmsg.c new file mode 100644 index 00000000..8a512f2b --- /dev/null +++ b/CASA-auth-token/client/core/gettokenmsg.c @@ -0,0 +1,793 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Parse states +// +#define AWAITING_ROOT_ELEMENT_START 0x0 +#define AWAITING_ROOT_ELEMENT_END 0x1 +#define AWAITING_STATUS_ELEMENT_START 0x2 +#define AWAITING_STATUS_ELEMENT_END 0x3 +#define AWAITING_STATUS_DATA 0x4 +#define AWAITING_DESCRIPTION_ELEMENT_START 0x5 +#define AWAITING_DESCRIPTION_ELEMENT_END 0x6 +#define AWAITING_DESCRIPTION_DATA 0x7 +#define AWAITING_LIFETIME_DATA 0x8 +#define AWAITING_LIFETIME_ELEMENT_START 0x9 +#define AWAITING_LIFETIME_ELEMENT_END 0xA +#define AWAITING_AUTH_TOKEN_ELEMENT_START 0xB +#define AWAITING_AUTH_TOKEN_ELEMENT_END 0xC +#define AWAITING_AUTH_TOKEN_DATA 0xD +#define DONE_PARSING 0xE + +// +// Get Authentication Token Response Parse Structure +// +typedef struct _GetAuthTokenRespParse +{ + XML_Parser p; + int state; + int elementDataProcessed; + GetAuthTokenResp *pGetAuthTokenResp; + CasaStatus status; + +} GetAuthTokenRespParse, *PGetAuthTokenRespParse; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//++======================================================================= +char* +BuildGetAuthTokenMsg( + IN const char *pServiceName, + IN const char *pHostName, + IN char *pSessionToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pMsg = NULL; + int bufferSize; + + DbgTrace(1, "-BuildGetAuthTokenMsg- Start\n", 0); + + /* + * The format of the get authentication token request message + * is as follows: + * + * + * + * service name + * host name + * session token data + * + * + */ + + // Determine the buffer size necessary to hold the msg + bufferSize = strlen(XML_DECLARATION) + + 2 // crlf + + 1 // < + + strlen(GET_AUTH_TOKEN_REQUEST_ELEMENT_NAME) + + 3 // >crlf + + 1 // < + + strlen(SERVICE_ELEMENT_NAME) + + 1 // > + + strlen(pServiceName) + + 2 // crlf + + 1 // < + + strlen(HOST_ELEMENT_NAME) + + 1 // > + + strlen(pHostName) + + 2 // crlf + + 1 // < + + strlen(SESSION_TOKEN_ELEMENT_NAME) + + 1 // > + + strlen(pSessionToken) + + 2 // crlf + + 2 // null + + // Allocate the msg buffer + pMsg = (char*) malloc(bufferSize); + if (pMsg) + { + // Now build the message + memset(pMsg, 0, bufferSize); + strcat(pMsg, XML_DECLARATION); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, GET_AUTH_TOKEN_REQUEST_ELEMENT_NAME); + strcat(pMsg, ">\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, SERVICE_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pServiceName); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, HOST_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pHostName); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, SESSION_TOKEN_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pSessionToken); + strcat(pMsg, "\r\n"); + strcat(pMsg, ""); + } + else + { + DbgTrace(0, "-BuildGetAuthTokenMsg- Buffer allocation error\n", 0); + } + + DbgTrace(1, "-BuildGetAuthTokenMsg- End, pMsg = %0lX\n", (long) pMsg); + + return pMsg; +} + + +//++======================================================================= +static +void XMLCALL +GetAuthTokenRespStartElementHandler( + IN GetAuthTokenRespParse *pGetAuthTokenRespParse, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthTokenRespStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pGetAuthTokenRespParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the Get Authentication + // Token Response Element. + if (strcmp(name, GET_AUTH_TOKEN_RESPONSE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_STATUS_ELEMENT_START; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_STATUS_ELEMENT_START: + + // In this state, we are only expecting the Status Element. + if (strcmp(name, STATUS_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_DESCRIPTION_ELEMENT_START; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_DESCRIPTION_ELEMENT_START: + + // In this state, we are only expecting the Description Element. + if (strcmp(name, DESCRIPTION_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_DESCRIPTION_DATA; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_TOKEN_ELEMENT_START: + + // In this state, we are only expecting the Authentication Token Element. + if (strcmp(name, AUTH_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_LIFETIME_ELEMENT_START; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_ELEMENT_START: + + // In this state, we are only expecting the Lifetime Element. + if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_LIFETIME_DATA; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected state = %d\n", pGetAuthTokenRespParse->state); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-GetAuthTokenRespStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +ConsumeElementData( + IN GetAuthTokenRespParse *pGetAuthTokenRespParse, + IN const XML_Char *s, + IN int len, + INOUT char **ppElementData, + INOUT int *pElementDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + + DbgTrace(3, "-ConsumeElementData- Start\n", 0); + + // Proceed based on whether or not we have already consumed data + // for this element. + if (*ppElementData == NULL) + { + // We have not yet consumed data for this element + pGetAuthTokenRespParse->elementDataProcessed = len; + + // Allocate a buffer to hold this element data (null terminated). + *ppElementData = (char*) malloc(len + 1); + if (*ppElementData) + { + memset(*ppElementData, 0, len + 1); + memcpy(*ppElementData, s, len); + + // Return the length of the element data buffer + *pElementDataLen = pGetAuthTokenRespParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + char *pNewBuf; + + // We have already received token data, append this data to it. + pNewBuf = (char*) malloc(pGetAuthTokenRespParse->elementDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pGetAuthTokenRespParse->elementDataProcessed + len + 1); + memcpy(pNewBuf, + *ppElementData, + pGetAuthTokenRespParse->elementDataProcessed); + memcpy(pNewBuf + pGetAuthTokenRespParse->elementDataProcessed, s, len); + pGetAuthTokenRespParse->elementDataProcessed += len; + + // Swap the buffers + free(*ppElementData); + *ppElementData = pNewBuf; + + // Return the length of the element data buffer + *pElementDataLen = pGetAuthTokenRespParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + DbgTrace(3, "-ConsumeElementData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +void XMLCALL +GetAuthTokenRespCharDataHandler( + IN GetAuthTokenRespParse *pGetAuthTokenRespParse, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthTokenRespCharDataHandler- Start\n", 0); + + // Just exit if being called to process white space + if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') + { + goto exit; + } + + // Proceed based on the state + switch (pGetAuthTokenRespParse->state) + { + case AWAITING_DESCRIPTION_DATA: + case AWAITING_DESCRIPTION_ELEMENT_END: + + // Ignore the status description data for now. + // tbd + + // Advanced to the next state + pGetAuthTokenRespParse->state = AWAITING_DESCRIPTION_ELEMENT_END; + break; + + case AWAITING_STATUS_DATA: + + // Set the appropriate status in the AuthenticationResp based on the + // returned status. + if (strncmp(HTTP_OK_STATUS_CODE, s, len) == 0) + { + pGetAuthTokenRespParse->status = CASA_STATUS_SUCCESS; + } + else if (strncmp(HTTP_UNAUTHORIZED_STATUS_CODE, s, len) == 0) + { + pGetAuthTokenRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_AUTHENTICATION_FAILURE); + } + else if (strncmp(HTTP_SERVER_ERROR_STATUS_CODE, s, len) == 0) + { + pGetAuthTokenRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_SERVER_ERROR); + } + else + { + DbgTrace(0, "-GetAuthTokenRespCharDataHandler- Un-expected status\n", 0); + pGetAuthTokenRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Advanced to the next state + pGetAuthTokenRespParse->state = AWAITING_STATUS_ELEMENT_END; + break; + + case AWAITING_LIFETIME_DATA: + + // Convert the lifetime string to a numeric value + pGetAuthTokenRespParse->pGetAuthTokenResp->tokenLifetime = dtoul(s, len); + + // Advanced to the next state + pGetAuthTokenRespParse->state = AWAITING_LIFETIME_ELEMENT_END; + break; + + case AWAITING_AUTH_TOKEN_DATA: + case AWAITING_AUTH_TOKEN_ELEMENT_END: + + // Consume the data + pGetAuthTokenRespParse->status = ConsumeElementData(pGetAuthTokenRespParse, + s, + len, + &pGetAuthTokenRespParse->pGetAuthTokenResp->pToken, + &pGetAuthTokenRespParse->pGetAuthTokenResp->tokenLen); + if (CASA_SUCCESS(pGetAuthTokenRespParse->status)) + { + // Advanced to the next state + pGetAuthTokenRespParse->state = AWAITING_AUTH_TOKEN_ELEMENT_END; + } + else + { + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-GetAuthTokenRespCharDataHandler- Un-expected state = %d\n", pGetAuthTokenRespParse->state); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-GetAuthTokenRespCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +GetAuthTokenRespEndElementHandler( + IN GetAuthTokenRespParse *pGetAuthTokenRespParse, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthTokenRespEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pGetAuthTokenRespParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the Get Authentication + // Token Response Element. + if (strcmp(name, GET_AUTH_TOKEN_RESPONSE_ELEMENT_NAME) == 0) + { + // Done. + pGetAuthTokenRespParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndHandler- Un-expected end element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_DESCRIPTION_ELEMENT_END: + + // In this state, we are only expecting the Description Element. + if (strcmp(name, DESCRIPTION_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_STATUS_DATA; + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_STATUS_ELEMENT_END: + + // In this state, we are only expecting the Status Element. + if (strcmp(name, STATUS_ELEMENT_NAME) == 0) + { + // Good, advance to the next state based on the status code. + if (CASA_SUCCESS(pGetAuthTokenRespParse->status)) + { + // The request completed successfully + pGetAuthTokenRespParse->state = AWAITING_AUTH_TOKEN_ELEMENT_START; + } + else + { + pGetAuthTokenRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_ELEMENT_END: + + // In this state, we are only expecting the Lifetime Element. + if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_AUTH_TOKEN_DATA; + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_TOKEN_ELEMENT_END: + + // In this state, we are only expecting the Authentication Token Element. + if (strcmp(name, AUTH_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected state = %d\n", pGetAuthTokenRespParse->state); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-GetAuthTokenRespEndElementHandler- End\n", 0); +} + + +//++======================================================================= +CasaStatus +CreateGetAuthTokenResp( + IN char *pRespMsg, + IN int respLen, + INOUT GetAuthTokenResp **ppGetAuthTokenResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + GetAuthTokenRespParse getAuthTokenRespParse = {0}; + GetAuthTokenResp *pGetAuthTokenResp; + + DbgTrace(1, "-CreateGetAuthTokenResp- Start\n", 0); + + /* + * When a get authentication token request is processed successfully, the + * server replies to the client with a message with the following format: + * + * + * + * ok200 + * lifetime valuesession token data + * + * + * When a get authentication token request fails to be successfully processed, + * the server responds with an error and an error description string. The message + * format of an unsuccessful reply is as follows: + * + * + * + * status descriptionstatus code + * + * + * Plase note that the protocol utilizes the status codes defined + * in the HTTP 1.1 Specification. + * + */ + + // Allocate GetAuthTokenResp object + pGetAuthTokenResp = malloc(sizeof(*pGetAuthTokenResp)); + if (pGetAuthTokenResp) + { + XML_Parser p; + + // Initialize the GetAuthTokenResp object and set it in the + // parse oject. + memset(pGetAuthTokenResp, 0, sizeof(*pGetAuthTokenResp)); + getAuthTokenRespParse.pGetAuthTokenResp = pGetAuthTokenResp; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + getAuthTokenRespParse.p = p; + + // Initialize the status within the parse object + getAuthTokenRespParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + (XML_StartElementHandler) GetAuthTokenRespStartElementHandler, + (XML_EndElementHandler) GetAuthTokenRespEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, (XML_CharacterDataHandler) GetAuthTokenRespCharDataHandler); + + + // Set our user data + XML_SetUserData(p, &getAuthTokenRespParse); + + // Parse the document + if (XML_Parse(p, pRespMsg, respLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (getAuthTokenRespParse.state == DONE_PARSING) + { + // The parse operation succeded, obtain the status returned + // by the server. + retStatus = getAuthTokenRespParse.status; + } + else + { + DbgTrace(0, "-CreateGetAuthTokenResp- Parse operation did not complete\n", 0); + + // Check if a status has been recorded + if (getAuthTokenRespParse.status != CASA_STATUS_SUCCESS) + { + retStatus = getAuthTokenRespParse.status; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + } + else + { + DbgTrace(0, "-CreateGetAuthTokenResp- Parse error %d\n", XML_GetErrorCode(p)); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + + // Free the parser + XML_ParserFree(p); + } + else + { + DbgTrace(0, "-CreateGetAuthTokenResp- Parser creation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Return the AuthenticationResp object to the caller if necessary + if (CASA_SUCCESS(retStatus)) + { + *ppGetAuthTokenResp = pGetAuthTokenResp; + } + else + { + free(pGetAuthTokenResp); + } + } + else + { + DbgTrace(0, "-CreateGetAuthTokenResp- Memory allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + DbgTrace(1, "-CreateGetAuthTokenResp- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +RelGetAuthTokenResp( + IN GetAuthTokenResp *pGetAuthTokenResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-RelGetAuthTokenResp- Start\n", 0); + + // Free the resources associated with the object + if (pGetAuthTokenResp->pToken) + free(pGetAuthTokenResp->pToken); + + free(pGetAuthTokenResp); + + DbgTrace(1, "-RelGetAuthTokenResp- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/internal.h b/CASA-auth-token/client/core/internal.h new file mode 100644 index 00000000..11d9a779 --- /dev/null +++ b/CASA-auth-token/client/core/internal.h @@ -0,0 +1,437 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +//===[ Include files ]===================================================== + +#include "platform.h" +#include +#include +#include +#include +#include "list_entry.h" +#include "config_if.h" +#include "mech_if.h" +#include "proto.h" + +//===[ Type definitions ]================================================== + +// +// Authentication Context structure +// +typedef struct _AuthContext +{ + LIST_ENTRY listEntry; + char *pContext; + int contextLen; + char *pMechanism; + int mechanismLen; + char *pMechInfo; + int mechInfoLen; + +} AuthContext, *PAuthContext; + +// +// Authentication Policy structure +// +typedef struct _AuthPolicy +{ + LIST_ENTRY authContextListHead; + +} AuthPolicy, *PAuthPolicy; + +// +// Get Authentication Policy Response structure +// +typedef struct _GetAuthPolicyResp +{ + char *pPolicy; + int policyLen; + +} GetAuthPolicyResp, *PGetAuthPolicyResp; + +// +// Get Authentication Token Response structure +// +typedef struct _GetAuthTokenResp +{ + char *pToken; + int tokenLen; + int tokenLifetime; + +} GetAuthTokenResp, *PGetAuthTokenResp; + +// +// Authenticate Response structure +// +typedef struct _AuthenticateResp +{ + char *pToken; + int tokenLen; + int tokenLifetime; + +} AuthenticateResp, *PAuthenticateResp; + +// +// Auth Cache Entry definition +// +typedef struct _AuthCacheEntry +{ + int status; + DWORD creationTime; + DWORD expirationTime; + bool doesNotExpire; + char token[1]; + +} AuthCacheEntry, *PAuthCacheEntry; + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +extern char clientConfigFolder[]; + +extern char mechConfigFolder[]; + +extern char pathCharString[]; + + +//===[ External prototypes ]=============================================== + +// +// Functions exported by engine.c +// + +extern +CasaStatus +ObtainAuthTokenInt( + IN const char *pServiceName, + IN const char *pHostName, + INOUT char *pAuthTokenBuf, + INOUT int *pAuthTokenBufLen, + IN void *pCredStoreScope); + +// +// Functions exported by authmech.c +// + +extern +CasaStatus +GetAuthMechToken( + IN AuthContext *pAuthContext, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char **ppAuthMechToken); + +// +// Functions exported by getpolicymsg.c +// + +extern +char* +BuildGetAuthPolicyMsg( + IN const char *pServiceName, + IN const char *pHostName); + +extern +CasaStatus +CreateGetAuthPolicyResp( + IN char *pRespMsg, + IN int respLen, + INOUT GetAuthPolicyResp **ppGetAuthPolicyResp); + +extern +void +RelGetAuthPolicyResp( + IN GetAuthPolicyResp *pGetAuthPolicyResp); + +// +// Functions exported by authpolicy.c +// + +extern +CasaStatus +CreateAuthPolicy( + IN char *pEncodedData, + IN int encodedDataLen, + INOUT AuthPolicy **ppAuthPolicy); + +extern +void +RelAuthPolicy( + IN AuthPolicy *pAuthPolicy); + +// +// Functions exported by authmsg.c +// + +extern +char* +BuildAuthenticateMsg( + IN AuthContext *pAuthContext, + IN char *pAuthMechToken); + +extern +CasaStatus +CreateAuthenticateResp( + IN char *pRespMsg, + IN int respLen, + INOUT AuthenticateResp **ppAuthenticateResp); + +extern +void +RelAuthenticateResp( + IN AuthenticateResp *pAuthenticateResp); + +// +// Functions exported by gettokenmsg.c +// + +extern +char* +BuildGetAuthTokenMsg( + IN const char *pServiceName, + IN const char *pHostName, + IN char *pSessionToken); + +extern +CasaStatus +CreateGetAuthTokenResp( + IN char *pRespMsg, + IN int respLen, + INOUT GetAuthTokenResp **ppGetAuthTokenResp); + +extern +void +RelGetAuthTokenResp( + IN GetAuthTokenResp *pGetAuthTokenResp); + +// +// Functions exported by cache.c +// + +extern +AuthCacheEntry* +CreateSessionTokenCacheEntry( + IN const char *pCacheKey, + IN CasaStatus status, + IN char *pToken, + IN int entryLifetime, + IN void *pCredStoreScope); + +extern +AuthCacheEntry* +CreateAuthTokenCacheEntry( + IN const char *pCacheKey, + IN const char *pHostName, + IN CasaStatus status, + IN char *pToken, + IN int entryLifetime, + IN void *pCredStoreScope); + +extern +void +FreeAuthCacheEntry( + IN AuthCacheEntry *pEntry); + +extern +AuthCacheEntry* +FindSessionTokenEntryInCache( + IN const char *pCacheKey, + IN void *pCredStoreScope); + +extern +AuthCacheEntry* +FindAuthTokenEntryInCache( + IN const char *pCacheKey, + IN const char *pGroupOrHostName, + IN void *pCredStoreScope); + +extern +CasaStatus +InitializeAuthCache(void); + +// +// Functions exported by config.c +// + +extern +CasaStatus +GetConfigInterface( + IN const char *pConfigFolder, + IN const char *pConfigName, + INOUT ConfigIf **ppConfigIf); + +// +// Functions exported by platform.c +// + +extern +CasaStatus +CreateUserMutex( + HANDLE *phMutex + ); + +extern +void +AcquireUserMutex( + HANDLE hMutex + ); + +extern +void +ReleaseUserMutex( + HANDLE hMutex + ); + +extern +void +DestroyUserMutex( + HANDLE hMutex + ); + +extern +LIB_HANDLE +OpenLibrary( + IN char *pFileName); + +extern +void +CloseLibrary( + IN LIB_HANDLE libHandle); + +extern +void* +GetFunctionPtr( + IN LIB_HANDLE libHandle, + IN char *pFunctionName); + +extern +char* +NormalizeHostName( + IN const char *pHostName); + +extern +CasaStatus +InitializeHostNameNormalization(void); + +// +// Functions exported by rpc.c +// + +extern +RpcSession* +OpenRpcSession( + IN const char *pHostName, + IN const uint16_t hostPort); + +extern +void +CloseRpcSession( + IN RpcSession *pSession); + +#define SECURE_RPC_FLAG 1 +#define ALLOW_INVALID_CERTS_RPC_FLAG 2 +#define ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG 4 + +extern +CasaStatus +Rpc( + IN RpcSession *pSession, + IN char *pMethod, + IN long flags, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen); + +extern +CasaStatus +InitializeRpc(void); + +// +// Functions exported by utils.c +// + +extern +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen); + +extern +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen); + +extern +int +dtoul( + IN const char *cp, + IN const int len); + +// +// Functions exported by invalidcert.c +// + +extern +bool +InvalidCertsFromHostAllowed( + IN char *pHostName); + +extern +void +AllowInvalidCertsFromHost( + IN char *pHostName); + +#define INVALID_CERT_CA_FLAG 1 +#define INVALID_CERT_CN_FLAG 2 +#define INVALID_CERT_DATE_FLAG 4 + +extern +bool +UserApprovedCert( + IN char *pHostName, + IN char *pCertSubject, + IN char *pCertIssuer, + IN long invalidCertFlags); + + +//========================================================================= + +#endif // _INTERNAL_H_ + diff --git a/CASA-auth-token/client/core/invalidcert.c b/CASA-auth-token/client/core/invalidcert.c new file mode 100644 index 00000000..a4a4fb63 --- /dev/null +++ b/CASA-auth-token/client/core/invalidcert.c @@ -0,0 +1,140 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//++======================================================================= +bool +InvalidCertsFromHostAllowed( + IN char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + bool retStatus = false; + + DbgTrace(2, "-InvalidCertsFromHostAllowed- Start\n", 0); + + // tbd + + DbgTrace(2, "-InvalidCertsFromHostAllowed- End, retStatus = %0X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +AllowInvalidCertsFromHost( + IN char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + bool retStatus = true; + + DbgTrace(2, "-AllowInvalidCertsFromHost- Start\n", 0); + + // tbd + + DbgTrace(2, "-AllowInvalidCertsFromHost- End\n", 0); +} + + +//++======================================================================= +bool +UserApprovedCert( + IN char *pHostName, + IN char *pCertSubject, + IN char *pCertIssuer, + IN long invalidCertFlags) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + bool retStatus = false; + + DbgTrace(2, "-UserApprovedCert- Start\n", 0); + + // tbd + + if (invalidCertFlags & INVALID_CERT_CN_FLAG) + { + DbgTrace(0, "-UserApprovedCert- Invalid Cert from Host = %s\n", pHostName); + } + if (invalidCertFlags & INVALID_CERT_CA_FLAG) + { + DbgTrace(0, "-UserApprovedCert- Invalid CA in Cert from Host = %s\n", pHostName); + } + if (invalidCertFlags & INVALID_CERT_DATE_FLAG) + { + DbgTrace(0, "-UserApprovedCert- Invalid DATE in Cert from Host = %s\n", pHostName); + } + DbgTrace(0, "-UserApprovedCert- Approving Invalid Cert from Host = %s\n", pHostName); + DbgTrace(0, "-UserApprovedCert- Invalid Cert Subject = %s\n", pCertSubject); + DbgTrace(0, "-UserApprovedCert- Invalid Cert Issuer = %s\n", pCertIssuer); + + DbgTrace(2, "-UserApprovedCert- End, retStatus = %0X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/linux/Makefile.am b/CASA-auth-token/client/core/linux/Makefile.am new file mode 100644 index 00000000..36347e62 --- /dev/null +++ b/CASA-auth-token/client/core/linux/Makefile.am @@ -0,0 +1,126 @@ +####################################################################### +# +# 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 +# +####################################################################### + +if DEBUG +TARGET_CFG = Debug +CFLAGS += -v -w +DEFINES = -DDBG +else +TARGET_CFG = Release +DEFINES = -DNDEBUG +endif + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../.. + +LIBDIR = $(ROOT)/$(LIB) + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +PLATFORMINDEPENDENTSOURCEDIR = .. +PLATFORMDEPENDENTSOURCEDIR = . + +MODULE_NAME = libcasa_c_authtoken +MODULE_EXT = so + +CFILES = ../authmech.c \ + ../authmsg.c \ + ../authpolicy.c \ + ../cache.c \ + ../config.c \ + ../engine.c \ + ../getpolicymsg.c \ + ../gettokenmsg.c \ + ../util.c \ + ../invalidcert.c \ + rpc.c \ + platform.c + +CSFILES_CSC := +INCLUDES = -I. -I.. -I../../include +RESOURCES = + +if LIB64 +DEFINES += -D_LIB64 +endif + +CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(INCLUDES) $(DEFINES) +LIBS = -lpthread -ldl -lexpat -lcurl -lidn -lssl -lcrypto -lz -lmicasa +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(ROOT)/lib/$(TARGET_CFG) + +OBJDIR = ./$(TARGET_CFG)/$(LIB) +OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) + +EXTRA_DIST = $(CFILES) *.h + +CUR_DIR := $(shell pwd) + +all: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + +# +# Pattern based rules. +# +vpath %.c $(PLATFORMDEPENDENTSOURCEDIR) $(PLATFORMINDEPENDENTSOURCEDIR) +vpath %.cpp $(PLATFORMDEPENDENTSOURCEDIR) $(PLATFORMINDEPENDENTSOURCEDIR) + +$(OBJDIR)/%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< + +$(OBJDIR)/%.o: %.cpp + $(CC) -c $(CFLAGS) -o $@ $< + +$(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT): $(OBJDIR) $(OBJS) + @echo [======== Linking $@ ========] + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + cp -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT) + +$(OBJDIR): + [ -d $(OBJDIR) ] || mkdir -p $(OBJDIR) + [ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) + [ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG) + + +install-exec-local: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(DESTDIR)$(libdir)/ + +uninstall-local: + cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + rmdir $(DESTDIR)$(libdir) + +#installcheck-local: install +# $(mkinstalldirs) $(DESTDIR)$(libdir) +# $(INSTALL_PROGRAM) $(DESTDIR)$(libdir) +# cd $(DESTDIR)$(libdir); $(MONO) + +clean-local: + if [ -d $(TARGET_CFG) ]; then rm -rf $(TARGET_CFG); fi + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/client/core/linux/platform.c b/CASA-auth-token/client/core/linux/platform.c new file mode 100644 index 00000000..32482f8d --- /dev/null +++ b/CASA-auth-token/client/core/linux/platform.c @@ -0,0 +1,831 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Normalized Host Name Cache Entry definition +// +typedef struct _NormalizedHostNameCacheEntry +{ + LIST_ENTRY listEntry; + char *pHostName; + char *pNormalizedHostName; + int buffLengthRequired; + +} NormalizedHostNameCacheEntry, *PNormalizedHostNameCacheEntry; + + +//===[ Type definitions for Local_sem ]==================================== +// +// Notes: Most of the code for this definitions and the Local_sem_xxxx +// functions was copied with minor modifications from W. Richard +// Stevens book: UNIX Network Programming, Interprocess +// Communications (Printed in 1999). +// +// You may ask, why not just use Posix Named Semaphores? The answer +// is that I wish that I could but I can not tolerate that they are +// not released when the process that holds them terminates abnormally. +// + +union semun /* define union for semctl() */ +{ + int val; + struct semid_ds *buf; + unsigned short *array; +}; + +typedef struct +{ + int sem_semid; /* the System V semaphore ID */ + int sem_magic; /* magic number if open */ + +} Local_sem_t; + +#ifndef SEM_R +#define SEM_R 0400 +#endif + +#ifndef SEM_A +#define SEM_A 0200 +#endif + +#define SVSEM_MODE (SEM_R | SEM_A | SEM_R>>3 | SEM_R>>6) + +#define SEM_MAGIC 0x45678923 + +#define SEM_FAILED ((Local_sem_t *)(-1)) /* avoid compiler warnings */ + +#ifndef SEMVMX +#define SEMVMX 32767 /* historical System V max value for sem */ +#endif + +#define MAX_OPEN_SEM_TRIES 10 /* for waiting for initialization */ + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Normalized host name cache variables +static +LIST_ENTRY normalizedHostNameCacheListHead; + +static +pthread_mutex_t g_hNormalizedHostNameCacheMutex = PTHREAD_MUTEX_INITIALIZER; + +// Client configuration file folder +char clientConfigFolder[] = "/etc/CASA/authtoken/client"; + +// Authentication mechanism configuration file folder +char mechConfigFolder[] = "/etc/CASA/authtoken/client/mechanisms"; + +// Module Synchronization mutex +pthread_mutex_t g_hModuleMutex = PTHREAD_MUTEX_INITIALIZER; + +// Path separator +char pathCharString[] = "/"; + +// Milliseconds per System Tick +static +long g_milliSecondsPerTicks = 0; + +// Named Semaphore for user variables +static +char g_userNamedSemName[256]; + +static +Local_sem_t *g_userNamedSem = SEM_FAILED; + +static +bool g_userNamedSemAcquired = false; + + +//++======================================================================= +Local_sem_t* +Local_sem_open(const char *pathname, int oflag, ... ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: Most of the code for this routine was copied with minor +// modifications from W. Richard Stevens book: UNIX Network +// Programming, Interprocess Communications (Printed in 1999). +// +// L2 +//=======================================================================-- +{ + int i, fd, semflag, semid, save_errno; + key_t key; + mode_t mode; + va_list ap; + Local_sem_t *sem; + union semun arg; + unsigned int value; + struct semid_ds seminfo; + struct sembuf initop; + + /* 4no mode for sem_open() w/out O_CREAT; guess */ + semflag = SVSEM_MODE; + semid = -1; + + if (oflag & O_CREAT) { + va_start(ap, oflag); /* init ap to final named argument */ + mode = va_arg(ap, mode_t); + value = va_arg(ap, unsigned int); + va_end(ap); + + /* 4convert to key that will identify System V semaphore */ + if ( (fd = open(pathname, oflag, mode)) == -1) + return(SEM_FAILED); + close(fd); + if ( (key = ftok(pathname, 0)) == (key_t) -1) + return(SEM_FAILED); + + semflag = IPC_CREAT | (mode & 0777); + if (oflag & O_EXCL) + semflag |= IPC_EXCL; + + /* 4create the System V semaphore with IPC_EXCL */ + if ( (semid = semget(key, 1, semflag | IPC_EXCL)) >= 0) { + /* 4success, we're the first so initialize to 0 */ + arg.val = 0; + if (semctl(semid, 0, SETVAL, arg) == -1) + goto err; + /* 4then increment by value to set sem_otime nonzero */ + if (value > SEMVMX) { + errno = EINVAL; + goto err; + } + initop.sem_num = 0; + initop.sem_op = value; + initop.sem_flg = 0; + if (semop(semid, &initop, 1) == -1) + goto err; + goto finish; + + } else if (errno != EEXIST || (semflag & IPC_EXCL) != 0) + goto err; + /* else fall through */ + } + + /* + * (O_CREAT not secified) or + * (O_CREAT without O_EXCL and semaphore already exists). + * Must open semaphore and make certain it has been initialized. + */ + if ( (key = ftok(pathname, 0)) == (key_t) -1) + goto err; + if ( (semid = semget(key, 0, semflag)) == -1) + goto err; + + arg.buf = &seminfo; + for (i = 0; i < MAX_OPEN_SEM_TRIES; i++) { + if (semctl(semid, 0, IPC_STAT, arg) == -1) + goto err; + if (arg.buf->sem_otime != 0) + goto finish; + sleep(1); + } + errno = ETIMEDOUT; +err: + save_errno = errno; /* don't let semctl() change errno */ + if (semid != -1) + semctl(semid, 0, IPC_RMID); + errno = save_errno; + return(SEM_FAILED); + +finish: + if ( (sem = malloc(sizeof(Local_sem_t))) == NULL) + goto err; + sem->sem_semid = semid; + sem->sem_magic = SEM_MAGIC; + return(sem); +} + + +//++======================================================================= +int +Local_sem_wait(Local_sem_t *sem) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: Most of the code for this routine was copied with minor +// modifications from W. Richard Stevens book: UNIX Network +// Programming, Interprocess Communications (Printed in 1999). +// +// L2 +//=======================================================================-- +{ + struct sembuf op; + + if (sem->sem_magic != SEM_MAGIC) { + errno = EINVAL; + return(-1); + } + + op.sem_num = 0; + op.sem_op = -1; + //op.sem_flg = 0; + op.sem_flg = SEM_UNDO; // Deviation from Richard's to allow cleanup in case of abnormal termination. + if (semop(sem->sem_semid, &op, 1) < 0) + return(-1); + return(0); +} + + +//++======================================================================= +int +Local_sem_post(Local_sem_t *sem) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: Most of the code for this routine was copied with minor +// modifications from W. Richard Stevens book: UNIX Network +// Programming, Interprocess Communications (Printed in 1999). +// +// L2 +//=======================================================================-- +{ + struct sembuf op; + + if (sem->sem_magic != SEM_MAGIC) { + errno = EINVAL; + return(-1); + } + + op.sem_num = 0; + op.sem_op = 1; + op.sem_flg = 0; + if (semop(sem->sem_semid, &op, 1) < 0) + return(-1); + return(0); +} + + +//++======================================================================= +int +Local_sem_close(Local_sem_t *sem) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: Most of the code for this routine was copied with minor +// modifications from W. Richard Stevens book: UNIX Network +// Programming, Interprocess Communications (Printed in 1999). +// +// L2 +//=======================================================================-- +{ + if (sem->sem_magic != SEM_MAGIC) { + errno = EINVAL; + return(-1); + } + sem->sem_magic = 0; /* just in case */ + + free(sem); + return(0); +} + + +//++======================================================================= +DWORD +GetTickCount(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + struct tms tm; + DWORD tickCount; + + DbgTrace(2, "-GetTickCount- Start\n", 0); + + // Determine milliseconds per tick if we have not done already + if (g_milliSecondsPerTicks == 0) + { + long ticksPerSecond; + + ticksPerSecond = sysconf(_SC_CLK_TCK); + DbgTrace(3, "-GetTickCount- TicksPerSec = %0lX\n", ticksPerSecond); + g_milliSecondsPerTicks = 1000 / ticksPerSecond; + } + + // Determine the tickCount as milliseconds + tickCount = g_milliSecondsPerTicks * times(&tm); + + DbgTrace(2, "-GetTickCount- End, retValue = %0lX\n", tickCount); + + return tickCount; +} + + +//++======================================================================= +CasaStatus +CreateUserMutex( + HANDLE *phMutex + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + + DbgTrace(1, "-CreateUserMutex- Start\n", 0); + + // We use Named Semaphores to provide this functionality. The semaphore names are + // linked to the user via its uid. + if (sprintf(g_userNamedSemName, "/var/lib/CASA/authtoken/semuser_%d", geteuid()) != -1) + { + // Create or open semaphore to be only used by the effective user + g_userNamedSem = Local_sem_open((const char*) g_userNamedSemName, O_RDWR | O_CREAT, 0600, 1); + if (g_userNamedSem == SEM_FAILED) + { + DbgTrace(0, "-CreateUserMutex- Error opening named semaphore, errno = %d\n", errno); + } + else + { + // Success + retStatus = CASA_STATUS_SUCCESS; + } + } + else + { + DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", errno); + } + + DbgTrace(1, "-CreateUserMutex- End, retStatus\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +AcquireUserMutex( + HANDLE hMutex + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-AcquireUserMutex- Start\n", 0); + + // Wait on the named semaphore + if (Local_sem_wait(g_userNamedSem) != 0) + { + DbgTrace(0, "-AcquireUserMutex- Error returned by sem_wait(), errno = %d\n", errno); + } + + // The user semaphore has been acquired + g_userNamedSemAcquired = true; + + DbgTrace(2, "-AcquireUserMutex- End\n", 0); +} + + +//++======================================================================= +void +ReleaseUserMutex( + HANDLE hMutex + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-ReleaseUserMutex- Start\n", 0); + + // The user semaphore is no longer acquired + g_userNamedSemAcquired = false; + + // Post on the named semaphore + if (Local_sem_post(g_userNamedSem) != 0) + { + DbgTrace(0, "-ReleaseUserMutex- Error returned by sem_post(), errno = %d\n", errno); + } + + DbgTrace(2, "-ReleaseUserMutex- End\n", 0); +} + + +//++======================================================================= +void +DestroyUserMutex( + HANDLE hMutex + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-DestroyUserMutex- Start\n", 0); + + // Do not do anything if the named semaphore is invalid + if (g_userNamedSem != SEM_FAILED) + { + // Close the named semaphore. Note that we want user semaphores to + // hang around, therefore we will not unlink them. This is per-design as + // is not a resource leak. If someone has an issue with this, then it can + // be solved by installing a cron job that cleans up the semaphores for + // deleted users. + if (Local_sem_close(g_userNamedSem) != 0) + { + DbgTrace(0, "-DestroyUserMutex- Error returned by sem_close(), errno = %d\n", errno); + } + + // Forget about the semaphore + g_userNamedSem = SEM_FAILED; + } + + DbgTrace(2, "-DestroyUserMutex- End\n", 0); +} + + +//++======================================================================= +LIB_HANDLE +OpenLibrary( + IN char *pFileName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + LIB_HANDLE libHandle; + + DbgTrace(1, "-OpenLibrary- Start\n", 0); + + libHandle = dlopen(pFileName, RTLD_LAZY); + if (libHandle == NULL) + { + DbgTrace(0, "-OpenLibrary- Not able to load library, error = %s\n", dlerror()); + } + + DbgTrace(1, "-OpenLibrary- End, handle = %0lX\n", (long) libHandle); + + return libHandle; +} + + +//++======================================================================= +void +CloseLibrary( + IN LIB_HANDLE libHandle) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-CloseLibrary- Start\n", 0); + + dlclose(libHandle); + + DbgTrace(1, "-CloseLibrary- End\n", 0); +} + + +//++======================================================================= +void* +GetFunctionPtr( + IN LIB_HANDLE libHandle, + IN char *pFunctionName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + void *pFuncPtr; + + DbgTrace(1, "-GetFunctionPtr- Start\n", 0); + + pFuncPtr = dlsym(libHandle, pFunctionName); + if (pFuncPtr == NULL) + { + DbgTrace(0, "-GetFunctionPtr- Not able to obtain func ptr, error = %s\n", dlerror()); + } + + DbgTrace(1, "-GetFunctionPtr- End, pFuncPtr = %0lX\n", (long) pFuncPtr); + + return pFuncPtr; +} + + +//++======================================================================= +char* +NormalizeHostName( + IN const char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pNormalizedName = NULL; + LIST_ENTRY *pListEntry; + NormalizedHostNameCacheEntry *pEntry = NULL; + + DbgTrace(1, "-NormalizeHostName- Start\n", 0); + + // Obtain our synchronization mutex + pthread_mutex_lock(&g_hNormalizedHostNameCacheMutex); + + // First try to find an entry in the normalized host name cache + // for the host name provided. + pListEntry = normalizedHostNameCacheListHead.Flink; + while (pListEntry != &normalizedHostNameCacheListHead) + { + // Get pointer to the entry + pEntry = CONTAINING_RECORD(pListEntry, NormalizedHostNameCacheEntry, listEntry); + + // Check if the entry is for the host name + if (strcmp(pHostName, pEntry->pHostName) == 0) + { + // This entry corresponds to the given host name + break; + } + else + { + // The entry does not correspond to the given host name + pEntry = NULL; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Check if we found an entry in our cache for the given host name + if (pEntry) + { + // Entry found, obtain the normalized name from it. + pNormalizedName = (char*) malloc(pEntry->buffLengthRequired); + if (pNormalizedName) + { + // Copy the normalized name onto the allocated buffer + strcpy(pNormalizedName, pEntry->pNormalizedHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + // An entry was not found in our cache, create one. + pEntry = (NormalizedHostNameCacheEntry*) malloc(sizeof(NormalizedHostNameCacheEntry)); + if (pEntry) + { + // Zero the entry + memset(pEntry, 0, sizeof(*pEntry)); + + // Allocate a buffer to hold the host name in the entry + pEntry->pHostName = (char*) malloc(strlen(pHostName) + 1); + if (pEntry->pHostName) + { + struct hostent *pLookupResult; + struct sockaddr_in sockAddr = {0}; + + // Copy the host name given into the allocated buffer + strcpy(pEntry->pHostName, pHostName); + + // Now try to resolve the normalized name + pLookupResult = gethostbyname(pHostName); + if (pLookupResult && pLookupResult->h_addrtype == AF_INET) + { + char dnsHostName[NI_MAXHOST]; + + // Set up a sockaddr structure + sockAddr.sin_family = AF_INET; + sockAddr.sin_addr.s_addr = *((int*) pLookupResult->h_addr_list[0]); + + // Now try to resolve the name using DNS + if (getnameinfo((const struct sockaddr*) &sockAddr, + sizeof(sockAddr), + dnsHostName, + sizeof(dnsHostName), + NULL, + 0, + NI_NAMEREQD) == 0) + { + // We resolved the address to a DNS name, use it as the normalized name. + pEntry->buffLengthRequired = (int) strlen(dnsHostName) + 1; + pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); + if (pEntry->pNormalizedHostName) + { + // Copy the dns name + strcpy(pEntry->pNormalizedHostName, dnsHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", errno); + + // Not able to resolve the name in DNS, just use the host name as + // the normalized name. + pEntry->buffLengthRequired = (int) strlen(pHostName) + 1; + pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); + if (pEntry->pNormalizedHostName) + { + // Copy the host name + strcpy(pEntry->pNormalizedHostName, pHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Name resolution failed, error = %d\n", errno); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + + // Free the space allocated for the entry + free(pEntry); + } + + // Proceed based on whether or not we normalized the name + if (pEntry->pNormalizedHostName) + { + // The name was normalized, save the entry in our cache. + InsertHeadList(&normalizedHostNameCacheListHead, &pEntry->listEntry); + + // Return the normalized name present in the entry + pNormalizedName = (char*) malloc(pEntry->buffLengthRequired); + if (pNormalizedName) + { + // Copy the normalized name onto the allocated buffer + strcpy(pNormalizedName, pEntry->pNormalizedHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + // The host name was not normalized, free allocated resources. + if (pEntry->pHostName) + free(pEntry->pHostName); + free(pEntry); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + + // Release our synchronization mutex + pthread_mutex_unlock(&g_hNormalizedHostNameCacheMutex); + + DbgTrace(1, "-NormalizeHostName- End, pNormalizedName = %0lX\n", (long) pNormalizedName); + + return pNormalizedName; +} + + +//++======================================================================= +CasaStatus +InitializeHostNameNormalization(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + + DbgTrace(1, "-InitializeHostNameNormalization- Start\n", 0); + + // Initialize the cache list head + InitializeListHead(&normalizedHostNameCacheListHead); + + DbgTrace(1, "-InitializeHostNameNormalization- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/linux/platform.h b/CASA-auth-token/client/core/linux/platform.h new file mode 100644 index 00000000..db1b11b4 --- /dev/null +++ b/CASA-auth-token/client/core/linux/platform.h @@ -0,0 +1,130 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#define _GNU_SOURCE + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ +char printBuff[256]; \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + fprintf(stderr, "CASA_AuthToken %s", printBuff); \ + } \ +} +/*#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + openlog("CASA_AuthToken", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER); \ + syslog(LOG_USER | LOG_INFO, X, Y); \ + closelog(); \ + } \ +}*/ + + +// +// Rpc Session definition +// +typedef struct _RpcSession +{ + CURL *hCurl; + char *pPartialHttpUrl; + int partialHttpUrlLen; + char *pPartialHttpsUrl; + int partialHttpsUrlLen; + struct curl_slist *headers; + char *pRecvData; + int recvDataLen; + +} RpcSession, *PRpcSession; + + +// +// Other definitions +// +#define HANDLE void* +#define LIB_HANDLE void* +#define DWORD unsigned long + +#define AcquireModuleMutex pthread_mutex_lock(&g_hModuleMutex) +#define ReleaseModuleMutex pthread_mutex_unlock(&g_hModuleMutex) + +// +// Deal with function name mapping issues +// +#define _snprintf snprintf +#define stricmp strcasecmp + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + +extern +DWORD +GetTickCount(void); + +//===[ External data ]===================================================== + +extern pthread_mutex_t g_hModuleMutex; + + +//========================================================================= + diff --git a/CASA-auth-token/client/core/linux/rpc.c b/CASA-auth-token/client/core/linux/rpc.c new file mode 100644 index 00000000..253dbaed --- /dev/null +++ b/CASA-auth-token/client/core/linux/rpc.c @@ -0,0 +1,566 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +#define MAX_RPC_RETRIES 3 + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +size_t +CurlWriteCallback( + IN void *pData, + IN size_t dataItemSz, + IN size_t numDataItems, + IN RpcSession *pSession) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + size_t dataConsumed = numDataItems; + + DbgTrace(1, "-CurlWriteCallback- Start\n", 0); + + // Consume the data by keeping a copy of the data. Note that we may have + // already consumed some data in which case we need to allocate a new + // buffer big enough to hold all of it. + if (pSession->pRecvData == NULL) + { + // We have not yet consumed receive data for the current Rpc + pSession->pRecvData = (char*) malloc(numDataItems * dataItemSz); + if (pSession->pRecvData) + { + // Consume the data + memcpy(pSession->pRecvData, pData, numDataItems * dataItemSz); + pSession->recvDataLen = numDataItems * dataItemSz; + } + else + { + DbgTrace(0, "-CurlWriteCallback- Buffer allocation error\n", 0); + dataConsumed = CURLE_WRITE_ERROR; // To abort RPC + } + } + else + { + // We have already consumed receive data for the current Rpc, append the new data to it. + char *pNewRecvDataBuf = (char*) malloc(pSession->recvDataLen + (numDataItems * dataItemSz)); + if (pNewRecvDataBuf) + { + memcpy(pNewRecvDataBuf, pSession->pRecvData, pSession->recvDataLen); + memcpy(pNewRecvDataBuf + pSession->recvDataLen, pData, numDataItems * dataItemSz); + pSession->recvDataLen += numDataItems * dataItemSz; + free(pSession->pRecvData); + pSession->pRecvData = pNewRecvDataBuf; + } + else + { + DbgTrace(0, "-CurlWriteCallback- Buffer allocation error\n", 0); + dataConsumed = CURLE_WRITE_ERROR; // To abort RPC + + // Forget about already consumed data + free(pSession->pRecvData); + pSession->pRecvData = NULL; + } + } + + DbgTrace(1, "-CurlWriteCallback- End\n", 0); + + return dataConsumed; +} + + +//++======================================================================= +RpcSession* +OpenRpcSession( + IN const char *pHostName, + IN const uint16_t hostPort) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + RpcSession *pSession = NULL; + char *pPartialHttpUrl = NULL; + char *pPartialHttpsUrl = NULL; + int hostNameLen = strlen(pHostName); + + DbgTrace(1, "-OpenRpcSession- Start\n", 0); + + // Build the partial URL strings that may be used with this session. + pPartialHttpUrl = (char*) malloc(7 /*"http://"*/ + hostNameLen + 34 /*":XXXX/CasaAuthTokenSvc/Rpc?method="*/ + 1 /*NULL Terminator*/); + pPartialHttpsUrl = (char*) malloc(8 /*"https://"*/ + hostNameLen + 34 /*":XXXX/CasaAuthTokenSvc/Rpc?method="*/ + 1 /*NULL Terminator*/); + if (pPartialHttpUrl && pPartialHttpsUrl) + { + sprintf(pPartialHttpUrl, "http://%s:%d/CasaAuthTokenSvc/Rpc?method=", pHostName, hostPort); + sprintf(pPartialHttpsUrl, "https://%s:%d/CasaAuthTokenSvc/Rpc?method=", pHostName, hostPort); + + // Allocate space for the session + pSession = (RpcSession*) malloc(sizeof(*pSession)); + if (pSession) + { + // Zero the session structure + memset(pSession, 0, sizeof(*pSession)); + + // Get a curl handle + pSession->hCurl = curl_easy_init(); + if (pSession->hCurl != NULL) + { + CURLcode result; + bool setOptError = false; + + // Set necessary options on the handle + if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_NOSIGNAL, 0)) != CURLE_OK) + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_NOSIGNAL, code = %d\n", result); + setOptError = true; + } + + if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_USERAGENT, "CASA Client/1.0")) != CURLE_OK) + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_USERAGENT, code = %d\n", result); + setOptError = true; + } + + if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_POST, 1)) != CURLE_OK) + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_POST, code = %d\n", result); + setOptError = true; + } + + pSession->headers = curl_slist_append(pSession->headers, "Content-Type: text/html"); + pSession->headers = curl_slist_append(pSession->headers, "Expect:"); + if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_HTTPHEADER, pSession->headers)) != CURLE_OK) + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_HTTPHEADER, code = %d\n", result); + setOptError = true; + } + + if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_WRITEFUNCTION, CurlWriteCallback)) != CURLE_OK) + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_WRITEFUNCTION, code = %d\n", result); + setOptError = true; + } + + if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_WRITEDATA, pSession)) != CURLE_OK) + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_WRITEDATA, code = %d\n", result); + setOptError = true; + } + + // Now check if we succeded + if (setOptError == false) + { + // Success, finish setting up the session object. + pSession->pPartialHttpUrl = pPartialHttpUrl; + pSession->partialHttpUrlLen = strlen(pPartialHttpUrl); + pSession->pPartialHttpsUrl = pPartialHttpsUrl; + pSession->partialHttpsUrlLen = strlen(pPartialHttpsUrl); + + // Forget about the partial URL buffers so that they do not get deleted below + pPartialHttpUrl = NULL; + pPartialHttpsUrl = NULL; + } + else + { + // Failed to set a needed curl option + if (pSession->headers) + curl_slist_free_all(pSession->headers); + + curl_easy_cleanup(pSession->hCurl); + + free(pSession); + pSession = NULL; + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Error creating curl handle\n", 0); + free(pSession); + pSession = NULL; + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for rpc session\n", 0); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for URL\n", 0); + } + + // Free buffers not utilized + if (pPartialHttpUrl) + free(pPartialHttpUrl); + + if (pPartialHttpsUrl) + free(pPartialHttpsUrl); + + DbgTrace(2, "-OpenRpcSession- End, pSession = %0lX\n", (long) pSession); + + return pSession; +} + + +//++======================================================================= +void +CloseRpcSession( + IN RpcSession *pSession) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-CloseRpcSession- Start\n", 0); + + // Free any HTTP headers associated with the session + if (pSession->headers) + curl_slist_free_all(pSession->headers); + + // Close the curl handle associated with this session + curl_easy_cleanup(pSession->hCurl); + + // Free the space allocated for the session + if (pSession->pRecvData) + free(pSession->pRecvData); + + free(pSession->pPartialHttpUrl); + free(pSession->pPartialHttpsUrl); + + free(pSession); + + DbgTrace(1, "-CloseRpcSession- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +InternalRpc( + IN RpcSession *pSession, + IN char *pMethod, + IN long flags, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ +#define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated + + CasaStatus retStatus; + char *pPartialUrl; + int partialUrlLen; + char *pUrl; + CURLcode curlResult; + + DbgTrace(1, "-InternalRpc- Start\n", 0); + + // Initialize output parameters + *ppResponseData = NULL; + *pResponseDataLen = 0; + + // Setup the URL using the input parameters + if (flags & SECURE_RPC_FLAG) + { + pPartialUrl = pSession->pPartialHttpsUrl; + partialUrlLen = pSession->partialHttpsUrlLen; + + // Check if we need to ignore invalid CERTS + if (flags & ALLOW_INVALID_CERTS_RPC_FLAG) + { + if ((curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_SSL_VERIFYPEER, 0)) != CURLE_OK) + { + DbgTrace(0, "-InternalRpc- Error setting CURLOPT_SSL_VERIFYPEER, code = %d\n", curlResult); + } + + if ((curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_SSL_VERIFYHOST, 0)) != CURLE_OK) + { + DbgTrace(0, "-InternalRpc- Error setting CURLOPT_SSL_VERIFYHOST, code = %d\n", curlResult); + } + } + else + { + if ((curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_SSL_VERIFYPEER, 1)) != CURLE_OK) + { + DbgTrace(0, "-InternalRpc- Error setting CURLOPT_SSL_VERIFYPEER, code = %d\n", curlResult); + } + + if ((curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_SSL_VERIFYHOST, 2)) != CURLE_OK) + { + DbgTrace(0, "-InternalRpc- Error setting CURLOPT_SSL_VERIFYHOST, code = %d\n", curlResult); + } + } + + } + else + { + pPartialUrl = pSession->pPartialHttpUrl; + partialUrlLen = pSession->partialHttpUrlLen; + } + + pUrl = (char*) malloc(partialUrlLen + strlen(pMethod) + 1); + + if (pUrl) + { + strcpy(pUrl, pPartialUrl); + strcat(pUrl, pMethod); + + // Tell curl about the URL + curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_URL, pUrl); + if (curlResult == CURLE_OK) + { + // Tell curl about our post data + curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_POSTFIELDS, pRequestData); + if (curlResult == CURLE_OK) + { + // Tell curl about our post data len + curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_POSTFIELDSIZE, strlen(pRequestData)); + if (curlResult == CURLE_OK) + { + // Now do the HTTP request + curlResult = curl_easy_perform(pSession->hCurl); + if (curlResult == CURLE_OK) + { + // Get the HTTP Response code + long httpCompStatus; + curlResult = curl_easy_getinfo(pSession->hCurl, CURLINFO_RESPONSE_CODE, &httpCompStatus); + if (curlResult == CURLE_OK) + { + // Verify that the HTTP request was successfully completed by the server + if (httpCompStatus == 200) + { + // Success, return the response data to the caller. + retStatus = CASA_STATUS_SUCCESS; + *ppResponseData = pSession->pRecvData; + *pResponseDataLen = pSession->recvDataLen;; + + // Forget about the response data buffer to keep from freeing it. + pSession->pRecvData = NULL; + } + else + { + DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %ld\n", httpCompStatus); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Curl get info failed, code = %d\n", curlResult); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Curl perform failed, code = %d\n", curlResult); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Make sure that we never exit with a recv data buffer hanging off the session + if (pSession->pRecvData) + { + free(pSession->pRecvData); + pSession->pRecvData = NULL; + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_POSTFIELDSIZE, code = %d\n", curlResult); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_POSTFIELDS, code = %d\n", curlResult); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_URL, code = %d\n", curlResult); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Free the buffer used to hold the URL + free(pUrl); + } + else + { + DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-InternalRpc- End, retStatus = %d\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +Rpc( + IN RpcSession *pSession, + IN char *pMethod, + IN long flags, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int retries = 0; + + DbgTrace(1, "-Rpc- Start\n", 0); + + // Retry the RPC as needed + do + { + // Issue the RPC + retStatus = InternalRpc(pSession, + pMethod, + flags, + pRequestData, + ppResponseData, + pResponseDataLen); + + // Account for this try + retries ++; + + } while (CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE + && retries < MAX_RPC_RETRIES); + + DbgTrace(1, "-Rpc- End, retStatus = %d\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +InitializeRpc(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + + DbgTrace(1, "-InitializeRpc- Start\n", 0); + + // Perform libcurl initializatoin + CURLcode curlStatus = curl_global_init(CURL_GLOBAL_SSL); + if (curlStatus != 0) + { + DbgTrace(0, "-InitializeRpc- Error initializing libcurl, curlStatus = %08X\n", curlStatus); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + else + { + // Success + retStatus = CASA_STATUS_SUCCESS; + } + + DbgTrace(1, "-InitializeRpc- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/mech_if.h b/CASA-auth-token/client/core/mech_if.h new file mode 100644 index 00000000..7a690005 --- /dev/null +++ b/CASA-auth-token/client/core/mech_if.h @@ -0,0 +1,184 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +#ifndef _MECH_IF_H_ +#define _MECH_IF_H_ + + +//===[ Include files ]===================================================== + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +/************************************************************************** +*************************************************************************** +** ** +** Authentication Mechanism Token Interface Definitions ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +typedef +int +(SSCS_CALL *PFNAuthTokenIf_AddReference)( + IN const void *pIfInstance); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +//=======================================================================-- + + +//++======================================================================= +typedef +void +(SSCS_CALL *PFNAuthTokenIf_ReleaseReference)( + IN const void *pIfInstance); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Nothing. +// +// Description: +// Decreases interface reference count. The interface is deallocated if +// the reference count becomes zero. +//=======================================================================-- + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFNAuthTokenIf_GetAuthToken)( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pContext - +// Pointer to null terminated string containing mechanism specific +// context information. Another name for context is Authentication +// Realm. +// +// pMechInfo - +// Pointer to null terminated string containing mechanism specific +// information. This is information is provided by the server to +// aid the mechanism to generate an authentication token. For +// example, the mechanism information for a Kerberos mechanism +// may be the service principal name to which the user will be +// authenticating. +// +// pHostName - +// Pointer to null terminated string containing the name of the +// host where the ATS resides. +// +// pCredStoreScope - +// Pointer to CASA structure for scoping credential store access +// to specific users. This can only be leveraged when running in +// the context of System under Windows. +// +// pTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pUserNameBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified service. +//=======================================================================-- + + +// +// AuthMechToken Interface Object +// +typedef struct _AuthTokenIf +{ + PFNAuthTokenIf_AddReference addReference; + PFNAuthTokenIf_ReleaseReference releaseReference; + PFNAuthTokenIf_GetAuthToken getAuthToken; + +} AuthTokenIf, *PAuthTokenIf; + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFN_GetAuthTokenIfRtn)( + IN const ConfigIf *pModuleConfigIf, + INOUT AuthTokenIf **ppAuthTokenIf); +// +// Arguments: +// pModuleConfigIf - +// Pointer to configuration interface instance for the module. +// +// ppAuthTokenIf - +// Pointer to variable that will receive pointer to AuthTokenIf +// instance. +// +// Returns: +// Casa Status +// +// Description: +// Gets authentication token interface instance. +//=======================================================================-- + +#define GET_AUTH_TOKEN_INTERFACE_RTN_SYMBOL "GetAuthTokenInterface" +#define GET_AUTH_TOKEN_INTERFACE_RTN GetAuthTokenInterface + + +#endif // #ifndef _MECH_IF_H_ + diff --git a/CASA-auth-token/client/core/mechanisms/Makefile.am b/CASA-auth-token/client/core/mechanisms/Makefile.am new file mode 100644 index 00000000..be130a11 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/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 = krb5 pwd + +DIST_SUBDIRS = krb5 pwd + +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/client/core/mechanisms/krb5/Makefile.am b/CASA-auth-token/client/core/mechanisms/krb5/Makefile.am new file mode 100644 index 00000000..5abfab9d --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/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 = $(TARGET_OS) + +DIST_SUBDIRS = linux windows + +CFILES = *.c + +EXTRA_DIST = $(CFILES) *.h + +.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/client/core/mechanisms/krb5/README b/CASA-auth-token/client/core/mechanisms/krb5/README new file mode 100644 index 00000000..d2e696fd --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/README @@ -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 + * + ***********************************************************************/ +/*********************************************************************** + * + * README for krb5mech + * + ***********************************************************************/ + +INTRODUCTION + +krb5mech is a client authentication mechanism for the support of Kerberos 5 +authentication. The mechanism leverages the services of the native Kerberos 5 +client to obtain Kerberos Tokens that can be used for authenticating an entity +to a Kerberos service. + + +SECURITY CONSIDERATIONS + +The tokens that krb5mech generates are only utilized to authenticate the client +entity to the Kerberos service, because of this, auth_token relies on SSL for +server authentication. auth_token does not leverage the capabilities of GSSAPI +for data privacy and data integrity purposes. + + + + + + + + + + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/TODO b/CASA-auth-token/client/core/mechanisms/krb5/TODO new file mode 100644 index 00000000..d3df377c --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/TODO @@ -0,0 +1,13 @@ +/*********************************************************************** + * + * TODO for krb5mech + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for krb5mech. + +OUTSTANDING ITEMS + +None. diff --git a/CASA-auth-token/client/core/mechanisms/krb5/interface.c b/CASA-auth-token/client/core/mechanisms/krb5/interface.c new file mode 100644 index 00000000..2fbdf3f4 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/interface.c @@ -0,0 +1,207 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Authentication Token Interface instance data +// +typedef struct _AuthTokenIfInstance +{ + int refCount; + AuthTokenIf authTokenIf; + +} AuthTokenIfInstance, *PAuthTokenIfInstance; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// AuthTokenIf variables +static +int g_numAuthTokenIfObjs = 0; + + +//++======================================================================= +static +int SSCS_CALL +AuthTokenIf_AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + AuthTokenIfInstance *pAuthTokenIfInstance = CONTAINING_RECORD(pIfInstance, AuthTokenIfInstance, authTokenIf); + + DbgTrace(2, "-AuthTokenIf_AddReference- Start\n", 0); + + // Increment the reference count on the object + pAuthTokenIfInstance->refCount ++; + refCount = pAuthTokenIfInstance->refCount; + + DbgTrace(2, "-AuthTokenIf_AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +static +void SSCS_CALL +AuthTokenIf_ReleaseReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Nothing. +// +// Description: +// Decreases interface reference count. The interface is deallocated if +// the reference count becomes zero. +// +// L2 +//=======================================================================-- +{ + bool freeObj = false; + AuthTokenIfInstance *pAuthTokenIfInstance = CONTAINING_RECORD(pIfInstance, AuthTokenIfInstance, authTokenIf); + + DbgTrace(2, "-AuthTokenIf_ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + pAuthTokenIfInstance->refCount --; + if (pAuthTokenIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numAuthTokenIfObjs --; + } + + // Free object if necessary + if (freeObj) + free(pAuthTokenIfInstance); + + DbgTrace(2, "-AuthTokenIf_ReleaseReference- End\n", 0); +} + + +//++======================================================================= +CasaStatus SSCS_CALL +GET_AUTH_TOKEN_INTERFACE_RTN( + IN const ConfigIf *pModuleConfigIf, + INOUT AuthTokenIf **ppAuthTokenIf) +// +// Arguments: +// pModuleConfigIf - +// Pointer to configuration interface instance for the module. +// +// ppAuthTokenIf - +// Pointer to variable that will receive pointer to AuthTokenIf +// instance. +// +// Returns: +// Casa Status +// +// Description: +// Gets authentication token interface instance. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + AuthTokenIfInstance *pAuthTokenIfInstance; + + + DbgTrace(1, "-GetAuthTokenInterface- Start\n", 0); + + // Validate input parameters + if (pModuleConfigIf == NULL + || ppAuthTokenIf == NULL) + { + DbgTrace(0, "-GetAuthTokenInterface- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Allocate space for the interface instance + pAuthTokenIfInstance = malloc(sizeof(*pAuthTokenIfInstance)); + if (pAuthTokenIfInstance) + { + // Initialize the interface instance data + pAuthTokenIfInstance->refCount = 1; + pAuthTokenIfInstance->authTokenIf.addReference = AuthTokenIf_AddReference; + pAuthTokenIfInstance->authTokenIf.releaseReference = AuthTokenIf_ReleaseReference; + pAuthTokenIfInstance->authTokenIf.getAuthToken = AuthTokenIf_GetAuthToken; + + // Keep track of this object + g_numAuthTokenIfObjs ++; + + // Return the interface to the caller + *ppAuthTokenIf = &pAuthTokenIfInstance->authTokenIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetAuthTokenInterface- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + +exit: + + DbgTrace(1, "-GetAuthTokenInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/internal.h b/CASA-auth-token/client/core/mechanisms/krb5/internal.h new file mode 100644 index 00000000..4a7fa49f --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/internal.h @@ -0,0 +1,92 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +//===[ Include files ]===================================================== + +#include "platform.h" +#include +#include +#include "config_if.h" +#include "mech_if.h" + +//===[ Type definitions ]================================================== + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +//===[ External prototypes ]=============================================== + +// +// Defined in get.c +// + +extern +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen); + +extern +int +InitializeLibrary(void); + +// +// Defined in utils.c +// + +extern +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen); + +extern +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen); + + +//========================================================================= + +#endif // _INTERNAL_H_ diff --git a/CASA-auth-token/client/core/mechanisms/krb5/linux/Krb5Authenticate.conf b/CASA-auth-token/client/core/mechanisms/krb5/linux/Krb5Authenticate.conf new file mode 100644 index 00000000..df2ad167 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/linux/Krb5Authenticate.conf @@ -0,0 +1,12 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# Krb5Authenticate # +# # +####################################################### + +LibraryName /usr/lib/CASA/authtoken/krb5mech.so + + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/linux/Krb5Authenticate_lib64.conf b/CASA-auth-token/client/core/mechanisms/krb5/linux/Krb5Authenticate_lib64.conf new file mode 100644 index 00000000..c1bc0bb6 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/linux/Krb5Authenticate_lib64.conf @@ -0,0 +1,12 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# Krb5Authenticate # +# # +####################################################### + +LibraryName /usr/lib64/CASA/authtoken/krb5mech.so + + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/linux/Makefile.am b/CASA-auth-token/client/core/mechanisms/krb5/linux/Makefile.am new file mode 100644 index 00000000..0dc23daf --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/linux/Makefile.am @@ -0,0 +1,122 @@ +####################################################################### +# +# 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 +# +####################################################################### + +if DEBUG +TARGET_CFG = Debug +CFLAGS += -v -w +DEFINES = -DDBG +else +TARGET_CFG = Release +DEFINES = -DNDEBUG +endif + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../../../.. + +LIBDIR = $(ROOT)/$(LIB) + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +PLATFORMINDEPENDENTSOURCEDIR = .. +PLATFORMDEPENDENTSOURCEDIR = . + +MODULE_NAME = krb5mech +MODULE_EXT = so + +CFILES = get.c \ + ../interface.c \ + ../util.c \ + platform.c + +CSFILES_CSC := +INCLUDES = -I. -I.. -I../../.. -I$(ROOT)/include +RESOURCES = + +DEST_CONF_FILE_NAME = Krb5Authenticate.conf +if LIB64 +DEFINES += -D_LIB64 +SRC_CONF_FILE_NAME = Krb5Authenticate_lib64.conf +else +SRC_CONF_FILE_NAME = Krb5Authenticate.conf +endif + +CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(INCLUDES) $(DEFINES) +LIBS = -lpthread -lc -lgssapi +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(ROOT)/lib/$(TARGET_CFG) + +OBJDIR = ./$(TARGET_CFG)/$(LIB) +OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) + +EXTRA_DIST = $(CFILES) *.h Krb5Authenticate.conf Krb5Authenticate_lib64.conf + +CUR_DIR := $(shell pwd) + +all: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + +# +# Pattern based rules. +# +vpath %.c $(PLATFORMDEPENDENTSOURCEDIR) $(PLATFORMINDEPENDENTSOURCEDIR) +vpath %.cpp $(PLATFORMDEPENDENTSOURCEDIR) $(PLATFORMINDEPENDENTSOURCEDIR) + +$(OBJDIR)/%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< + +$(OBJDIR)/%.o: %.cpp + $(CC) -c $(CFLAGS) -o $@ $< + +$(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT): $(OBJDIR) $(OBJS) + @echo [======== Linking $@ ========] + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + cp -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT) + cp -f $(SRC_CONF_FILE_NAME) $(LIBDIR)/$(TARGET_CFG)/$(DEST_CONF_FILE_NAME) + +$(OBJDIR): + [ -d $(OBJDIR) ] || mkdir -p $(OBJDIR) + [ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) + [ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG) + +install-exec-local: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(DESTDIR)$(libdir)/ + +uninstall-local: + cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + rmdir $(DESTDIR)$(libdir) + +#installcheck-local: install +# $(mkinstalldirs) $(DESTDIR)$(libdir) +# $(INSTALL_PROGRAM) $(DESTDIR)$(libdir) +# cd $(DESTDIR)$(libdir); $(MONO) + +clean-local: + if [ -d $(TARGET_CFG) ]; then rm -rf $(TARGET_CFG); fi + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/linux/get.c b/CASA-auth-token/client/core/mechanisms/krb5/linux/get.c new file mode 100644 index 00000000..2c08d447 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/linux/get.c @@ -0,0 +1,385 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Mechanism OID +gss_OID g_mechOid = GSS_C_NULL_OID; + + +//++======================================================================= +void +LogGssStatuses( + IN char *operation, + IN OM_uint32 majorGssStatus, + IN OM_uint32 minorGssStatus) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + OM_uint32 gssMajStat; + OM_uint32 gssMinStat; + gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; + OM_uint32 gssMsgCtx; + + // Trace the messages associated with the major status + gssMsgCtx = 0; + while (1) + { + gssMajStat = gss_display_status(&gssMinStat, + majorGssStatus, + GSS_C_GSS_CODE, + g_mechOid, + &gssMsgCtx, + &msg); + if (gssMajStat != GSS_S_COMPLETE) + { + DbgTrace(0, "-LogGssStatuses- Error obtaining display status\n", 0); + break; + } + + // Trace this message + DbgTrace(0, "-LogGssStatuses- GSS-API error %s: ", operation); + DbgTrace(0, "%s\n", (char *)msg.value); + + if (msg.length != 0) + gss_release_buffer(&gssMinStat, &msg); + + if (!gssMsgCtx) + break; + } + + // Trace the messages associated with the minor status + gssMsgCtx = 0; + while (1) + { + gssMajStat = gss_display_status(&gssMinStat, + minorGssStatus, + GSS_C_MECH_CODE, + g_mechOid, + &gssMsgCtx, + &msg); + if (gssMajStat != GSS_S_COMPLETE) + { + DbgTrace(0, "-LogGssStatuses- Error obtaining display status\n", 0); + break; + } + + // Trace this message + DbgTrace(0, "-LogGssStatuses- GSS-API error %s: ", operation); + DbgTrace(0, "%s\n", (char *)msg.value); + + if (msg.length != 0) + gss_release_buffer(&gssMinStat, &msg); + + if (!gssMsgCtx) + break; + } +} + + +//++======================================================================= +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pServiceConfigIf - +// Pointer to service config object to which the client is trying to +// authenticate. +// +// pContext - +// Pointer to null terminated string containing mechanism specific +// context information. Another name for context is Authentication +// Realm. +// +// pMechInfo - +// Pointer to null terminated string containing mechanism specific +// information. This is information is provided by the server to +// aid the mechanism to generate an authentication token. For +// example, the mechanism information for a Kerberos mechanism +// may be the service principal name to which the user will be +// authenticating. +// +// pHostName - +// Pointer to null terminated string containing the name of the +// host where the ATS resides. +// +// pCredStoreScope - +// Pointer to CASA structure for scoping credential store access +// to specific users. This can only be leveraged when running in +// the context of System under Windows. +// +// pTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pUserNameBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified service. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + char const *pKrbServiceName = pMechInfo; + OM_uint32 gssMajStat; + OM_uint32 gssMinStat; + gss_buffer_desc gssBuffer; + gss_name_t gssServiceName; + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0); + + // Validate input parameters + if (pIfInstance == NULL + || pContext == NULL + || pHostName == NULL + || pTokenBufLen == NULL + || (pTokenBuf == NULL && *pTokenBufLen != 0)) + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Check if we need to construct the service name + if (pKrbServiceName == NULL + || strlen(pKrbServiceName) == 0) + { + // The service name will default to host/hostname + pKrbServiceName = malloc(5 /*"host/"*/ + strlen(pHostName) + 1 /*'/0'*/); + if (pKrbServiceName) + { + sprintf(pKrbServiceName, "host/%s", pHostName); + } + else + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Memory allocation failure\n", 0); + goto exit; + } + } + + // Import the service principal name into something that + // GSS-API can understand based on its form. + gssBuffer.value = (void*) pKrbServiceName; + gssBuffer.length = strlen(pKrbServiceName) + 1; + if (strchr(pKrbServiceName, '@') != NULL) + { + // The name is of the form "servicename@hostname" + gssMajStat = gss_import_name(&gssMinStat, + &gssBuffer, + (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, + &gssServiceName); + } + else + { + // The name is of the form "servicename" + gssMajStat = gss_import_name(&gssMinStat, + &gssBuffer, + (gss_OID) GSS_C_NT_USER_NAME, + &gssServiceName); + } + + // Proceed based on the result of the name import operation + if (gssMajStat == GSS_S_COMPLETE) + { + // Establish a context + gss_ctx_id_t gssContext = GSS_C_NO_CONTEXT; + gss_buffer_desc gssSendToken = {0}; + OM_uint32 gssRetFlags; + gssMajStat = gss_init_sec_context(&gssMinStat, + GSS_C_NO_CREDENTIAL, + &gssContext, + gssServiceName, + g_mechOid, + 0, // Flags + 0, + NULL, // no channel bindings + GSS_C_NO_BUFFER, // no token from peer + NULL, // ignore mech type + &gssSendToken, + &gssRetFlags, + NULL); // ignore time rec + + // Proceed based on the result of the gss_init_sec_context operation + if (gssMajStat == GSS_S_COMPLETE + && gssSendToken.length != 0) + { + char *pEncodedToken; + int encodedTokenLen; + + // The security context was initialized, now return the token to the + // caller after base64 encoding it. + retStatus = EncodeData(gssSendToken.value, + gssSendToken.length, + &pEncodedToken, + &encodedTokenLen); + if (CASA_SUCCESS(retStatus)) + { + // Verify that the caller provided a buffer that is big enough + if (encodedTokenLen > *pTokenBufLen) + { + // At least one of the supplied buffers is not big enough + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Insufficient buffer space provided\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + else + { + // The buffer provided is large enough, copy the data and return the actual size. + memcpy((void*) pTokenBuf, pEncodedToken, encodedTokenLen +1); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + + // Return the actual size or the size required + *pTokenBufLen = encodedTokenLen; + + // Free the buffer containing the encoded token + free(pEncodedToken); + } + else + { + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Encoding failed\n", 0); + } + } + else + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Error initing sec context\n", 0); + LogGssStatuses("initializing context", gssMajStat, gssMinStat); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Release send token buffer if necessary + if (gssSendToken.length != 0) + gss_release_buffer(&gssMinStat, &gssSendToken); + + + // Free context if necessary + if (gssContext != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&gssMinStat, &gssContext, GSS_C_NO_BUFFER); + + // Release the buffer associated with the service name + gss_release_name(&gssMinStat, &gssServiceName); + } + else + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Error importing service name\n", 0); + LogGssStatuses("importing service name", gssMajStat, gssMinStat); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_OBJECT_NOT_FOUND); + } + +exit: + + // Free buffer holding the Krb Service Name if necessary + if (pKrbServiceName + && pKrbServiceName != pMechInfo) + free(pKrbServiceName); + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +InitializeLibrary(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = 0; + + DbgTrace(1, "-InitializeLibrary- Start\n", 0); + + // Nothing to do at this time. + + DbgTrace(1, "-InitializeLibrary- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/linux/platform.c b/CASA-auth-token/client/core/mechanisms/krb5/linux/platform.c new file mode 100644 index 00000000..869b581c --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/linux/platform.c @@ -0,0 +1,35 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/linux/platform.h b/CASA-auth-token/client/core/mechanisms/krb5/linux/platform.h new file mode 100644 index 00000000..72d3c254 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/linux/platform.h @@ -0,0 +1,90 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#define _GNU_SOURCE + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//===[ Type definitions ]================================================== + +#define HANDLE void* + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ +char printBuff[256]; \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + fprintf(stderr, "CASA_Krb5Mech %s", printBuff); \ + } \ +} +/*#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + openlog("CASA_Krb5Mech", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER); \ + syslog(LOG_USER | LOG_INFO, X, Y); \ + closelog(); \ + } \ +}*/ + + +// +// Deal with function name mapping issues +// +#define _snprintf snprintf + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + + + +//========================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/util.c b/CASA-auth-token/client/core/mechanisms/krb5/util.c new file mode 100644 index 00000000..90454c7a --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/util.c @@ -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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Debug Level +int DebugLevel = 0; + +// Tables for Base64 encoding and decoding +static const int8_t g_Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const uint8_t g_Expand64[256] = +{ + /* ASCII table */ + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 +}; + + +//++======================================================================= +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int encodedSize; + + char *pTmp; + + DbgTrace(3, "-EncodeData- Start\n", 0); + + // Determine the encoded size and allocate a buffer to hold the encoded data + encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4; + pTmp = (char*) malloc(encodedSize); + *ppEncodedData = pTmp; + if (*ppEncodedData) + { + uint8_t *pOut, *pIn; + int i; + + // Setup pointers to move through the buffers + pIn = (uint8_t*) pData; + pOut = (uint8_t*) *ppEncodedData; + + // Perform the encoding + for (i = 0; i < dataLen - 2; i += 3) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) | + ((int32_t)(pIn[i + 2] & 0xC0) >> 6)]; + *pOut++ = g_Base64[pIn[i + 2] & 0x3F]; + } + if (i < dataLen) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + if (i == (dataLen - 1)) + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4)]; + *pOut++ = '='; + } + else + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)]; + } + *pOut++ = '='; + } + *pOut++ = '\0'; + + // Return the encoded data length + *pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int i, j; + int decodedSize; + + DbgTrace(3, "-DecodeData- Start\n", 0); + + // Determine the decoded size + for (i = 0, j = 0; i < encodedDataLen; i++) + if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64) + j++; + decodedSize = (j * 3 + 3) / 4; + + // Allocate buffer to hold the decoded data + *ppData = malloc(decodedSize); + if (*ppData) + { + bool endReached = false; + uint8_t c0, c1, c2, c3; + uint8_t *p, *q; + + // Initialize parameters that will be used during the decode operation + c0 = c1 = c2 = c3 = 0; + p = (uint8_t*) pEncodedData; + q = (uint8_t*) *ppData; + + // Decode the data + // + // Loop through the data, piecing back information. Any newlines, and/or + // carriage returns need to be skipped. + while (j > 4) + { + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + endReached = true; + break; + } + c0 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2); + j--; + endReached = true; + break; + } + c1 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4); + j -= 2; + endReached = true; + break; + } + c2 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6); + j -= 3; + endReached = true; + break; + } + c3 = *(p++); + + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]); + j -= 4; + } + if (!endReached) + { + if (j > 1) + *(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4); + if (j > 2) + *(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2); + if (j > 3) + *(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]); + } + + // Return the length of the decoded data + *pDataLen = (int32_t)(q - (uint8_t*)*ppData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/windows/Krb5Authenticate.conf b/CASA-auth-token/client/core/mechanisms/krb5/windows/Krb5Authenticate.conf new file mode 100644 index 00000000..76cbd200 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/windows/Krb5Authenticate.conf @@ -0,0 +1,12 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# Krb5Authenticate # +# # +####################################################### + +LibraryName \Program Files\novell\casa\lib\krb5mech.dll + + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/windows/Makefile.am b/CASA-auth-token/client/core/mechanisms/krb5/windows/Makefile.am new file mode 100644 index 00000000..d7bb146f --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/windows/Makefile.am @@ -0,0 +1,69 @@ +####################################################################### +# +# Copyright (C) 2004 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: Greg Richardson +# +####################################################################### + +SUBDIRS = + +DIST_SUBDIRS = + +EXTRA_DIST = krb5.vcproj ../*.c *.c *.h *.conf *.def + +if DEBUG +TARGET_CFG = Debug +else +TARGET_CFG = Release +endif + +PACKAGE = krb5 +TARGET_FILE = krb5mech.dll +LOG_FILE = $(PACKAGE).log + +all-am: $(TARGET_FILE) + +.PHONY: $TARGET_FILE) devenv + +devenv: + @if ! test -x "$(VSINSTALLDIR)/devenv.exe"; then echo "Error: Microsoft Visual Studio .NET is currently required to build MSI and MSM packages"; exit 1; fi + +$(TARGET_FILE): devenv + @rm -f $(LOG_FILE) $@ + @CMD='"$(VSINSTALLDIR)/devenv.exe" ../../../../auth.sln /build $(TARGET_CFG) /project $(PACKAGE) /out $(LOG_FILE)'; \ + echo $$CMD; \ + if eval $$CMD; then \ + ls -l $(TARGET_CFG)/$(TARGET_FILE); \ + else \ + grep -a "ERROR:" $(LOG_FILE); \ + fi + +package-clean clean-local: + rm -rf Release/* Release Debug/* Debug*/Release */Debug *.log *.suo + +clean: + rm -rf Release/* Release Debug/* Debug */Release */Debug *.log *.suo + +distclean-local: package-clean + rm -f Makefile + +maintainer-clean-local: + rm -f Makefile.in + + + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/windows/dllsup.c b/CASA-auth-token/client/core/mechanisms/krb5/windows/dllsup.c new file mode 100644 index 00000000..1fbf8cc8 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/windows/dllsup.c @@ -0,0 +1,132 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ External data ]===================================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +UINT32 g_ulCount = 0; +UINT32 g_ulLock = 0; +HANDLE g_hModule; + + +//++======================================================================= +BOOL APIENTRY DllMain( + HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +//=======================================================================-- +{ + BOOL retStatus = TRUE; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + g_hModule = hModule; + + // Initialize the library + if (InitializeLibrary() != 0) + { + // Failed to initialize the library + OutputDebugString("CASA_KRB5_MECH -DllMain- Library initialization failed\n"); + retStatus = FALSE; + } + break; + } + + case DLL_THREAD_ATTACH: + { + g_hModule = hModule; + break; + } + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + { + /* Don't uninitialize on windows + tbd + */ + break; + } + } + + return retStatus; +} + +//++======================================================================= +// +// DllCanUnloadNow +// +// Synopsis +// +// +STDAPI +DllCanUnloadNow() +// +// Input Arguments +// +// Ouput Arguments +// +// Return Value +// S_OK The DLL can be unloaded. +// S_FALSE The DLL cannot be unloaded now. +// +// Description +// An Exported Function. +// DLLs that support the OLE Component Object Model (COM) should implement +// and export DllCanUnloadNow. +// A call to DllCanUnloadNow determines whether the DLL from which it is +// exported is still in use. A DLL is no longer in use when it is not +// managing any existing objects (the reference count on all of its objects +// is 0). +// DllCanUnloadNow returns S_FALSE if there are any existing references to +// objects that the DLL manages. +// +// Environment +// +// See Also +// +//=======================================================================-- +{ + // tbd + return ((g_ulCount == 0 && g_ulLock == 0) ? S_OK : S_FALSE); +} + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/windows/get.c b/CASA-auth-token/client/core/mechanisms/krb5/windows/get.c new file mode 100644 index 00000000..f1f1dddf --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/windows/get.c @@ -0,0 +1,300 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pContext - +// Pointer to null terminated string containing mechanism specific +// context information. Another name for context is Authentication +// Realm. +// +// pMechInfo - +// Pointer to null terminated string containing mechanism specific +// information. This is information is provided by the server to +// aid the mechanism to generate an authentication token. For +// example, the mechanism information for a Kerberos mechanism +// may be the service principal name to which the user will be +// authenticating. +// +// pHostName - +// Pointer to null terminated string containing the name of the +// host where the ATS resides. +// +// pCredStoreScope - +// Pointer to CASA structure for scoping credential store access +// to specific users. This can only be leveraged when running in +// the context of System under Windows. +// +// pTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pUserNameBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified service. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + char *pKrbServiceName = pMechInfo; + SECURITY_STATUS secStatus; + TimeStamp expiry; + CredHandle hCredentials = {0}; + + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0); + + // Validate input parameters + if (pIfInstance == NULL + || pContext == NULL + || pHostName == NULL + || pTokenBufLen == NULL + || (pTokenBuf == NULL && *pTokenBufLen != 0)) + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Check if we need to construct the service name + if (pKrbServiceName == NULL + || strlen(pKrbServiceName) == 0) + { + // The service name will default to host/hostname + pKrbServiceName = malloc(5 /*"host/"*/ + strlen(pHostName) + 1 /*'/0'*/); + if (pKrbServiceName) + { + sprintf(pKrbServiceName, "host/%s", pHostName); + } + else + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Memory allocation failure\n", 0); + goto exit; + } + } + + // Acquire a credential handle for the current user + secStatus = AcquireCredentialsHandle(NULL, // no principal name + "Kerberos", // package name + SECPKG_CRED_OUTBOUND, + NULL, // no logon id + NULL, // no auth data + NULL, // no get key fn + NULL, // noget key arg + &hCredentials, + &expiry); + if (secStatus == SEC_E_OK) + { + CtxtHandle hContext = {0}; + SecBuffer sendTok; + SecBufferDesc outputDesc; + ULONG retFlags; + + // We acquired the credential, now initialize a security context + // so that we can authenticate the user to the specified service. + // + // First ready an output descriptor so that we can receive the + // token buffer. + outputDesc.cBuffers = 1; + outputDesc.pBuffers = &sendTok; + outputDesc.ulVersion = SECBUFFER_VERSION; + + sendTok.BufferType = SECBUFFER_TOKEN; + sendTok.cbBuffer = 0; + sendTok.pvBuffer = NULL; + + // Initialize the security context for the specified service + secStatus = InitializeSecurityContext(&hCredentials, + NULL, + pKrbServiceName, + ISC_REQ_ALLOCATE_MEMORY, + 0, // reserved + SECURITY_NATIVE_DREP, + NULL, + 0, // reserved + &hContext, + &outputDesc, + &retFlags, + &expiry); + if (secStatus == SEC_E_OK) + { + char *pEncodedToken; + int encodedTokenLen; + + // The security context was initialized, now return it to the caller after base64 encoding it. + retStatus = EncodeData(sendTok.pvBuffer, + (const int) sendTok.cbBuffer, + &pEncodedToken, + &encodedTokenLen); + if (CASA_SUCCESS(retStatus)) + { + // Verify that the caller provided a buffer that is big enough + if (encodedTokenLen > *pTokenBufLen) + { + // The buffer is not big enough + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + else + { + // The buffer provided is large enough, copy the data. + memcpy((void*) pTokenBuf, pEncodedToken, encodedTokenLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + + // Return the actual size or the size required + *pTokenBufLen = encodedTokenLen; + + // Free the buffer containing the encoded token + free(pEncodedToken); + } + + // Delete the security context + DeleteSecurityContext(&hContext); + } + else + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Failed to initialize the security context, error = %08X\n", secStatus); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Free any buffer associated with the sendToken + if (sendTok.pvBuffer) + FreeContextBuffer(sendTok.pvBuffer); + + // Free the credential handle obtained + FreeCredentialsHandle(&hCredentials); + } + else + { + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Failed to obtain the credentials handle, error = %08X\n", secStatus); + + // Set retStatus based on secStatus + if (secStatus == SEC_E_NOT_OWNER + || secStatus == SEC_E_NO_CREDENTIALS) + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_NO_CREDENTIALS); + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + +exit: + + // Free buffer holding the Krb Service Name if necessary + if (pKrbServiceName + && pKrbServiceName != pMechInfo) + free(pKrbServiceName); + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +InitializeLibrary(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = 0; + + DbgTrace(1, "-InitializeLibrary- Start\n", 0); + + // Nothing to do at this time. + + DbgTrace(1, "-InitializeLibrary- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/windows/krb5.vcproj b/CASA-auth-token/client/core/mechanisms/krb5/windows/krb5.vcproj new file mode 100644 index 00000000..37a4152c --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/windows/krb5.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/windows/krb5mech.def b/CASA-auth-token/client/core/mechanisms/krb5/windows/krb5mech.def new file mode 100644 index 00000000..1605afcf --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/windows/krb5mech.def @@ -0,0 +1,10 @@ +LIBRARY KRB5MECH +DESCRIPTION 'CASA Kerberos V Authentication Mechanism Library.' + + +EXPORTS +; DllRegisterServer PRIVATE +; DllUnregisterServer PRIVATE +; DllGetClassObject PRIVATE + GetAuthTokenInterface PRIVATE +; DllCanUnloadNow PRIVATE \ No newline at end of file diff --git a/CASA-auth-token/client/core/mechanisms/krb5/windows/platform.c b/CASA-auth-token/client/core/mechanisms/krb5/windows/platform.c new file mode 100644 index 00000000..869b581c --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/windows/platform.c @@ -0,0 +1,35 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + diff --git a/CASA-auth-token/client/core/mechanisms/krb5/windows/platform.h b/CASA-auth-token/client/core/mechanisms/krb5/windows/platform.h new file mode 100644 index 00000000..1b3f0f7f --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/krb5/windows/platform.h @@ -0,0 +1,83 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +//#define DbgTrace(LEVEL, X, Y) { \ +//char printBuff[256]; \ +// if (LEVEL == 0 || DebugLevel >= LEVEL) \ +// { \ +// _snprintf(printBuff, sizeof(printBuff), X, Y); \ +// printf("Krb5Mech %s", printBuff); \ +// } \ +//} +#define DbgTrace(LEVEL, X, Y) { \ +char formatBuff[128]; \ +char printBuff[256]; \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + strcpy(formatBuff, "Krb5Mech "); \ + strncat(formatBuff, X, sizeof(formatBuff) - 9); \ + _snprintf(printBuff, sizeof(printBuff), formatBuff, Y); \ + OutputDebugString(printBuff); \ + } \ +} + +#define bool BOOLEAN +#define true TRUE +#define false FALSE + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + + +//========================================================================= + +#endif // _PLATFORM_H_ + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/Makefile.am b/CASA-auth-token/client/core/mechanisms/pwd/Makefile.am new file mode 100644 index 00000000..63055631 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/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 = $(TARGET_OS) + +DIST_SUBDIRS = linux windows + +CFILES = *.c + +EXTRA_DIST = $(CFILES) *.h + +.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/client/core/mechanisms/pwd/README b/CASA-auth-token/client/core/mechanisms/pwd/README new file mode 100644 index 00000000..002f9b8a --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/README @@ -0,0 +1,50 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ +/*********************************************************************** + * + * README for pwmech + * + ***********************************************************************/ + +INTRODUCTION + +pwmech is a client authentication mechanism for the support of username +and password authenticaton. The mechanism leverages the credentials stored +in the miCASA cache and does not prompt the user for credentials. + +SECURITY CONSIDERATIONS + +The tokens that pwmech generates contain the user's username and password, +this mandates that the auth_token client utilize a secure channel when +transfering them to the ATS. + + + + + + + + + + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/TODO b/CASA-auth-token/client/core/mechanisms/pwd/TODO new file mode 100644 index 00000000..08437725 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/TODO @@ -0,0 +1,13 @@ +/*********************************************************************** + * + * TODO for pwmech + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for pwmech. + +OUTSTANDING ITEMS + +None. diff --git a/CASA-auth-token/client/core/mechanisms/pwd/get.c b/CASA-auth-token/client/core/mechanisms/pwd/get.c new file mode 100644 index 00000000..cd8a8345 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/get.c @@ -0,0 +1,352 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +static +CasaStatus +GetUserCredentials( + IN const char *pRealm, + IN void *pCredStoreScope, + INOUT char **ppUsername, + INOUT char **ppPassword) +// +// Arguments: +// pRealm - +// The realm to which the credentials apply. +// +// pCredStoreScope - +// Pointer to CASA structure for scoping credential store access +// to specific users. This can only be leveraged when running in +// the context of System under Windows. +// +// ppUsername - +// Pointer to variable that will receive buffer with the username. +// +// ppPassword - +// Pointer to variable that will receive buffer with the password. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication credentials for the specified realm. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_UNSUCCESSFUL); + char *pUsername; + char *pPassword; + int rcode = NSSCS_E_OBJECT_NOT_FOUND; + uint32_t credtype = SSCS_CRED_TYPE_BASIC_F; + SSCS_BASIC_CREDENTIAL credential = {0}; + SSCS_SECRET_ID_T secretId = {0}; + + DbgTrace(1, "-GetUserCredentials- Start\n", 0); + + // Initialize output parameters + *ppUsername = NULL; + *ppPassword = NULL; + + // Get the length of the realm string into the secret id structure + // and verify thatr it is not too long. + secretId.len = sscs_Utf8Strlen(pRealm) + 1; + if (secretId.len <= NSSCS_MAX_SECRET_ID_LEN) + { + // Set the secret id in the structure + sscs_Utf8Strcpy((char*) secretId.id, pRealm); + + // Specify that we want the common name + credential.unFlags = USERNAME_TYPE_CN_F; + + // Now try to get the credentials + rcode = miCASAGetCredential(0, + &secretId, + NULL, + &credtype, + &credential, + (SSCS_EXT_T*) pCredStoreScope); + if (rcode != NSSCS_SUCCESS) + { + // There were no credentials for the realm, now try to obtain the + // desktop credentials. + secretId.len = sscs_Utf8Strlen("Desktop") + 1; + sscs_Utf8Strcpy((char*) secretId.id, "Desktop"); + rcode = miCASAGetCredential(0, + &secretId, + NULL, + &credtype, + &credential, + (SSCS_EXT_T*) pCredStoreScope); + } + } + else + { + DbgTrace(0, "-GetUserCredentials- Realm name too long\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Proceed based on the result of the operatiosn above + if (rcode == NSSCS_SUCCESS + && credential.username != NULL + && credential.password != NULL) + { + // Allocate a buffer to return the username + pUsername = (char*) malloc(strlen((char*) credential.username) + 1); + if (pUsername) + { + // Copy the username into the buffer that we will be returning + strcpy(pUsername, (char*) credential.username); + + // Allocate a buffer to return the password + pPassword = (char*) malloc(strlen((char*) credential.password) + 1); + if (pPassword) + { + // Copy the password into the buffer that we will be returning + strcpy(pPassword, (char*) credential.password); + + DbgTrace(1, "-GetUserCredentials- Username = %s\n", pUsername); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + + // Free the buffer allocated for the username + free(pUsername); + } + } + else + { + DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-GetUserCredentials- Failed to obtain credentials for pw authentication\n", 0); + } + + // Return the buffers to the caller if successful + if (CASA_SUCCESS(retStatus)) + { + *ppUsername = pUsername; + *ppPassword = pPassword; + } + + DbgTrace(1, "-GetUserCredentials- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pContext - +// Pointer to null terminated string containing mechanism specific +// context information. Another name for context is Authentication +// Realm. +// +// pMechInfo - +// Pointer to null terminated string containing mechanism specific +// information. This is information is provided by the server to +// aid the mechanism to generate an authentication token. For +// example, the mechanism information for a Kerberos mechanism +// may be the service principal name to which the user will be +// authenticating. +// +// pHostName - +// Pointer to null terminated string containing the name of the +// host where the ATS resides. +// +// pCredStoreScope - +// Pointer to CASA structure for scoping credential store access +// to specific users. This can only be leveraged when running in +// the context of System under Windows. +// +// pTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pUserNameBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified service. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + char *pUsername = NULL; + char *pPassword = NULL; + char *pToken; + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0); + + // Validate input parameters + if (pIfInstance == NULL + || pContext == NULL + || pHostName == NULL + || pTokenBufLen == NULL + || (pTokenBuf == NULL && *pTokenBufLen != 0)) + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Get the user credentials + retStatus = GetUserCredentials(pContext, + pCredStoreScope, + &pUsername, + &pPassword); + if (CASA_SUCCESS(retStatus)) + { + // Now construct the PW token with the following format: + // "username\r\n" + "password\r\n" + // + // First allocate a buffer large enough to hold the token + pToken = (char*) malloc(strlen(pUsername) + 2 + strlen(pPassword) + 2 + 1); + if (pToken) + { + char *pEncodedToken; + int encodedTokenLen; + + // Now assemble the token + sprintf(pToken, "%s\r\n%s\r\n", pUsername, pPassword); + + // The token has been assembled, now encode it. + retStatus = EncodeData(pToken, + (const int) strlen(pToken), + &pEncodedToken, + &encodedTokenLen); + if (CASA_SUCCESS(retStatus)) + { + // Verify that the caller provided a buffer that is big enough + if (encodedTokenLen > *pTokenBufLen) + { + // The buffer is not big enough + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + else + { + // The buffer provided is large enough, copy the data. + memcpy((void*) pTokenBuf, pEncodedToken, encodedTokenLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + + // Return the actual size or the size required + *pTokenBufLen = encodedTokenLen; + + // Free the buffer containing the encoded token + free(pEncodedToken); + } + + // Free the buffer allocated for the token + free(pToken); + } + else + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Free allocated buffers + free(pUsername); + free(pPassword); + } + else + { + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Failed to obtain the user credentials\n", 0); + } + +exit: + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/interface.c b/CASA-auth-token/client/core/mechanisms/pwd/interface.c new file mode 100644 index 00000000..2fbdf3f4 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/interface.c @@ -0,0 +1,207 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Authentication Token Interface instance data +// +typedef struct _AuthTokenIfInstance +{ + int refCount; + AuthTokenIf authTokenIf; + +} AuthTokenIfInstance, *PAuthTokenIfInstance; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// AuthTokenIf variables +static +int g_numAuthTokenIfObjs = 0; + + +//++======================================================================= +static +int SSCS_CALL +AuthTokenIf_AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + AuthTokenIfInstance *pAuthTokenIfInstance = CONTAINING_RECORD(pIfInstance, AuthTokenIfInstance, authTokenIf); + + DbgTrace(2, "-AuthTokenIf_AddReference- Start\n", 0); + + // Increment the reference count on the object + pAuthTokenIfInstance->refCount ++; + refCount = pAuthTokenIfInstance->refCount; + + DbgTrace(2, "-AuthTokenIf_AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +static +void SSCS_CALL +AuthTokenIf_ReleaseReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Nothing. +// +// Description: +// Decreases interface reference count. The interface is deallocated if +// the reference count becomes zero. +// +// L2 +//=======================================================================-- +{ + bool freeObj = false; + AuthTokenIfInstance *pAuthTokenIfInstance = CONTAINING_RECORD(pIfInstance, AuthTokenIfInstance, authTokenIf); + + DbgTrace(2, "-AuthTokenIf_ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + pAuthTokenIfInstance->refCount --; + if (pAuthTokenIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numAuthTokenIfObjs --; + } + + // Free object if necessary + if (freeObj) + free(pAuthTokenIfInstance); + + DbgTrace(2, "-AuthTokenIf_ReleaseReference- End\n", 0); +} + + +//++======================================================================= +CasaStatus SSCS_CALL +GET_AUTH_TOKEN_INTERFACE_RTN( + IN const ConfigIf *pModuleConfigIf, + INOUT AuthTokenIf **ppAuthTokenIf) +// +// Arguments: +// pModuleConfigIf - +// Pointer to configuration interface instance for the module. +// +// ppAuthTokenIf - +// Pointer to variable that will receive pointer to AuthTokenIf +// instance. +// +// Returns: +// Casa Status +// +// Description: +// Gets authentication token interface instance. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + AuthTokenIfInstance *pAuthTokenIfInstance; + + + DbgTrace(1, "-GetAuthTokenInterface- Start\n", 0); + + // Validate input parameters + if (pModuleConfigIf == NULL + || ppAuthTokenIf == NULL) + { + DbgTrace(0, "-GetAuthTokenInterface- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Allocate space for the interface instance + pAuthTokenIfInstance = malloc(sizeof(*pAuthTokenIfInstance)); + if (pAuthTokenIfInstance) + { + // Initialize the interface instance data + pAuthTokenIfInstance->refCount = 1; + pAuthTokenIfInstance->authTokenIf.addReference = AuthTokenIf_AddReference; + pAuthTokenIfInstance->authTokenIf.releaseReference = AuthTokenIf_ReleaseReference; + pAuthTokenIfInstance->authTokenIf.getAuthToken = AuthTokenIf_GetAuthToken; + + // Keep track of this object + g_numAuthTokenIfObjs ++; + + // Return the interface to the caller + *ppAuthTokenIf = &pAuthTokenIfInstance->authTokenIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetAuthTokenInterface- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + +exit: + + DbgTrace(1, "-GetAuthTokenInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/internal.h b/CASA-auth-token/client/core/mechanisms/pwd/internal.h new file mode 100644 index 00000000..b2a221d9 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/internal.h @@ -0,0 +1,90 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +//===[ Include files ]===================================================== + +#include "platform.h" +#include +#include +#include +#include +#include "config_if.h" +#include "mech_if.h" + +//===[ Type definitions ]================================================== + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +//===[ External prototypes ]=============================================== + +// +// Defined in get.c +// + +extern +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + IN const char *pHostName, + IN void *pCredStoreScope, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen); + +// +// Defined in utils.c +// + +extern +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen); + +extern +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen); + +//========================================================================= + +#endif // _INTERNAL_H_ + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/linux/Makefile.am b/CASA-auth-token/client/core/mechanisms/pwd/linux/Makefile.am new file mode 100644 index 00000000..372511f1 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/linux/Makefile.am @@ -0,0 +1,122 @@ +####################################################################### +# +# 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 +# +####################################################################### + +if DEBUG +TARGET_CFG = Debug +CFLAGS += -v -w +DEFINES = -DDBG +else +TARGET_CFG = Release +DEFINES = -DNDEBUG +endif + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../../../.. + +LIBDIR = $(ROOT)/$(LIB) + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +PLATFORMINDEPENDENTSOURCEDIR = .. +PLATFORMDEPENDENTSOURCEDIR = . + +MODULE_NAME = pwmech +MODULE_EXT = so + +CFILES = ../get.c \ + ../interface.c \ + ../util.c \ + platform.c + +CSFILES_CSC := +INCLUDES = -I. -I.. -I../../.. -I$(ROOT)/include +RESOURCES = + +DEST_CONF_FILE_NAME = PwdAuthenticate.conf +if LIB64 +DEFINES += -D_LIB64 +SRC_CONF_FILE_NAME = PwdAuthenticate_lib64.conf +else +SRC_CONF_FILE_NAME = PwdAuthenticate.conf +endif + +CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(INCLUDES) $(DEFINES) +LIBS = -lpthread -lmicasa +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(ROOT)/lib/$(TARGET_CFG) + +OBJDIR = ./$(TARGET_CFG)/$(LIB) +OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) + +EXTRA_DIST = $(CFILES) *.h PwdAuthenticate.conf PwdAuthenticate_lib64.conf + +CUR_DIR := $(shell pwd) + +all: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + +# +# Pattern based rules. +# +vpath %.c $(PLATFORMDEPENDENTSOURCEDIR) $(PLATFORMINDEPENDENTSOURCEDIR) +vpath %.cpp $(PLATFORMDEPENDENTSOURCEDIR) $(PLATFORMINDEPENDENTSOURCEDIR) + +$(OBJDIR)/%.o: %.c + $(CC) -c $(CFLAGS) -o $@ $< + +$(OBJDIR)/%.o: %.cpp + $(CC) -c $(CFLAGS) -o $@ $< + +$(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT): $(OBJDIR) $(OBJS) + @echo [======== Linking $@ ========] + $(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) + cp -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT) + cp -f $(SRC_CONF_FILE_NAME) $(LIBDIR)/$(TARGET_CFG)/$(DEST_CONF_FILE_NAME) + +$(OBJDIR): + [ -d $(OBJDIR) ] || mkdir -p $(OBJDIR) + [ -d $(LIBDIR) ] || mkdir -p $(LIBDIR) + [ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG) + +install-exec-local: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(DESTDIR)$(libdir)/ + +uninstall-local: + cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) + rmdir $(DESTDIR)$(libdir) + +#installcheck-local: install +# $(mkinstalldirs) $(DESTDIR)$(libdir) +# $(INSTALL_PROGRAM) $(DESTDIR)$(libdir) +# cd $(DESTDIR)$(libdir); $(MONO) + +clean-local: + if [ -d $(TARGET_CFG) ]; then rm -rf $(TARGET_CFG); fi + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/linux/PwdAuthenticate.conf b/CASA-auth-token/client/core/mechanisms/pwd/linux/PwdAuthenticate.conf new file mode 100644 index 00000000..f991c1a8 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/linux/PwdAuthenticate.conf @@ -0,0 +1,12 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# PwdAuthenticate # +# # +####################################################### + +LibraryName /usr/lib/CASA/authtoken/pwmech.so + + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/linux/PwdAuthenticate_lib64.conf b/CASA-auth-token/client/core/mechanisms/pwd/linux/PwdAuthenticate_lib64.conf new file mode 100644 index 00000000..f0435d9c --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/linux/PwdAuthenticate_lib64.conf @@ -0,0 +1,12 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# PwdAuthenticate # +# # +####################################################### + +LibraryName /usr/lib64/CASA/authtoken/pwmech.so + + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/linux/platform.c b/CASA-auth-token/client/core/mechanisms/pwd/linux/platform.c new file mode 100644 index 00000000..869b581c --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/linux/platform.c @@ -0,0 +1,35 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/linux/platform.h b/CASA-auth-token/client/core/mechanisms/pwd/linux/platform.h new file mode 100644 index 00000000..f2f6c09e --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/linux/platform.h @@ -0,0 +1,88 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#define _GNU_SOURCE + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//===[ Type definitions ]================================================== + +#define HANDLE void* + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ +char printBuff[256]; \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + fprintf(stderr, "CASA_PwMech %s", printBuff); \ + } \ +} +/*#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + openlog("CASA_PwMech", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER); \ + syslog(LOG_USER | LOG_INFO, X, Y); \ + closelog(); \ + } \ +}*/ + + +// +// Deal with function name mapping issues +// +#define _snprintf snprintf + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + + + +//========================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/util.c b/CASA-auth-token/client/core/mechanisms/pwd/util.c new file mode 100644 index 00000000..90454c7a --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/util.c @@ -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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Debug Level +int DebugLevel = 0; + +// Tables for Base64 encoding and decoding +static const int8_t g_Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const uint8_t g_Expand64[256] = +{ + /* ASCII table */ + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 +}; + + +//++======================================================================= +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int encodedSize; + + char *pTmp; + + DbgTrace(3, "-EncodeData- Start\n", 0); + + // Determine the encoded size and allocate a buffer to hold the encoded data + encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4; + pTmp = (char*) malloc(encodedSize); + *ppEncodedData = pTmp; + if (*ppEncodedData) + { + uint8_t *pOut, *pIn; + int i; + + // Setup pointers to move through the buffers + pIn = (uint8_t*) pData; + pOut = (uint8_t*) *ppEncodedData; + + // Perform the encoding + for (i = 0; i < dataLen - 2; i += 3) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) | + ((int32_t)(pIn[i + 2] & 0xC0) >> 6)]; + *pOut++ = g_Base64[pIn[i + 2] & 0x3F]; + } + if (i < dataLen) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + if (i == (dataLen - 1)) + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4)]; + *pOut++ = '='; + } + else + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)]; + } + *pOut++ = '='; + } + *pOut++ = '\0'; + + // Return the encoded data length + *pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int i, j; + int decodedSize; + + DbgTrace(3, "-DecodeData- Start\n", 0); + + // Determine the decoded size + for (i = 0, j = 0; i < encodedDataLen; i++) + if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64) + j++; + decodedSize = (j * 3 + 3) / 4; + + // Allocate buffer to hold the decoded data + *ppData = malloc(decodedSize); + if (*ppData) + { + bool endReached = false; + uint8_t c0, c1, c2, c3; + uint8_t *p, *q; + + // Initialize parameters that will be used during the decode operation + c0 = c1 = c2 = c3 = 0; + p = (uint8_t*) pEncodedData; + q = (uint8_t*) *ppData; + + // Decode the data + // + // Loop through the data, piecing back information. Any newlines, and/or + // carriage returns need to be skipped. + while (j > 4) + { + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + endReached = true; + break; + } + c0 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2); + j--; + endReached = true; + break; + } + c1 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4); + j -= 2; + endReached = true; + break; + } + c2 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6); + j -= 3; + endReached = true; + break; + } + c3 = *(p++); + + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]); + j -= 4; + } + if (!endReached) + { + if (j > 1) + *(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4); + if (j > 2) + *(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2); + if (j > 3) + *(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]); + } + + // Return the length of the decoded data + *pDataLen = (int32_t)(q - (uint8_t*)*ppData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/windows/Makefile.am b/CASA-auth-token/client/core/mechanisms/pwd/windows/Makefile.am new file mode 100644 index 00000000..fcf613f3 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/windows/Makefile.am @@ -0,0 +1,69 @@ +####################################################################### +# +# Copyright (C) 2004 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: Greg Richardson +# +####################################################################### + +SUBDIRS = + +DIST_SUBDIRS = + +EXTRA_DIST = pwd.vcproj ../*.c *.c *.h *.conf *.def + +if DEBUG +TARGET_CFG = Debug +else +TARGET_CFG = Release +endif + +PACKAGE = pwd +TARGET_FILE = pwmech.dll +LOG_FILE = $(PACKAGE).log + +all-am: $(TARGET_FILE) + +.PHONY: $TARGET_FILE) devenv + +devenv: + @if ! test -x "$(VSINSTALLDIR)/devenv.exe"; then echo "Error: Microsoft Visual Studio .NET is currently required to build MSI and MSM packages"; exit 1; fi + +$(TARGET_FILE): devenv + @rm -f $(LOG_FILE) $@ + @CMD='"$(VSINSTALLDIR)/devenv.exe" ../../../../auth.sln /build $(TARGET_CFG) /project $(PACKAGE) /out $(LOG_FILE)'; \ + echo $$CMD; \ + if eval $$CMD; then \ + ls -l $(TARGET_CFG)/$(TARGET_FILE); \ + else \ + grep -a "ERROR:" $(LOG_FILE); \ + fi + +package-clean clean-local: + rm -rf Release/* Release Debug/* Debug*/Release */Debug *.log *.suo + +clean: + rm -rf Release/* Release Debug/* Debug */Release */Debug *.log *.suo + +distclean-local: package-clean + rm -f Makefile + +maintainer-clean-local: + rm -f Makefile.in + + + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/windows/PwdAuthenticate.conf b/CASA-auth-token/client/core/mechanisms/pwd/windows/PwdAuthenticate.conf new file mode 100644 index 00000000..dd6c1eb5 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/windows/PwdAuthenticate.conf @@ -0,0 +1,12 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# PwdAuthenticate # +# # +####################################################### + +LibraryName \Program Files\novell\casa\lib\pwmech.dll + + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/windows/dllsup.c b/CASA-auth-token/client/core/mechanisms/pwd/windows/dllsup.c new file mode 100644 index 00000000..2aff8d4e --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/windows/dllsup.c @@ -0,0 +1,126 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ External data ]===================================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +UINT32 g_ulCount = 0; +UINT32 g_ulLock = 0; +HANDLE g_hModule; + + +//++======================================================================= +BOOL APIENTRY DllMain( + HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +//=======================================================================-- +{ + BOOL retStatus = TRUE; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + g_hModule = hModule; + + // Nothing else to do at this time + break; + } + + case DLL_THREAD_ATTACH: + { + g_hModule = hModule; + break; + } + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + { + /* Don't uninitialize on windows + tbd + */ + break; + } + } + + return retStatus; +} + +//++======================================================================= +// +// DllCanUnloadNow +// +// Synopsis +// +// +STDAPI +DllCanUnloadNow() +// +// Input Arguments +// +// Ouput Arguments +// +// Return Value +// S_OK The DLL can be unloaded. +// S_FALSE The DLL cannot be unloaded now. +// +// Description +// An Exported Function. +// DLLs that support the OLE Component Object Model (COM) should implement +// and export DllCanUnloadNow. +// A call to DllCanUnloadNow determines whether the DLL from which it is +// exported is still in use. A DLL is no longer in use when it is not +// managing any existing objects (the reference count on all of its objects +// is 0). +// DllCanUnloadNow returns S_FALSE if there are any existing references to +// objects that the DLL manages. +// +// Environment +// +// See Also +// +//=======================================================================-- +{ + // tbd + return ((g_ulCount == 0 && g_ulLock == 0) ? S_OK : S_FALSE); +} + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/windows/platform.c b/CASA-auth-token/client/core/mechanisms/pwd/windows/platform.c new file mode 100644 index 00000000..869b581c --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/windows/platform.c @@ -0,0 +1,35 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/windows/platform.h b/CASA-auth-token/client/core/mechanisms/pwd/windows/platform.h new file mode 100644 index 00000000..b447c1a9 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/windows/platform.h @@ -0,0 +1,81 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ + +//===[ Include files ]===================================================== + +#include +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +//#define DbgTrace(LEVEL, X, Y) { \ +//char printBuff[256]; \ +// if (LEVEL == 0 || DebugLevel >= LEVEL) \ +// { \ +// _snprintf(printBuff, sizeof(printBuff), X, Y); \ +// printf("PwdMech %s", printBuff); \ +// } \ +//} +#define DbgTrace(LEVEL, X, Y) { \ +char formatBuff[128]; \ +char printBuff[256]; \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + strcpy(formatBuff, "CASA_PwdMech "); \ + strncat(formatBuff, X, sizeof(formatBuff) - 8); \ + _snprintf(printBuff, sizeof(printBuff), formatBuff, Y); \ + OutputDebugString(printBuff); \ + } \ +} + +#define bool BOOLEAN +#define true TRUE +#define false FALSE + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + + +//========================================================================= + +#endif // _PLATFORM_H_ + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/windows/pwd.vcproj b/CASA-auth-token/client/core/mechanisms/pwd/windows/pwd.vcproj new file mode 100644 index 00000000..6502266e --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/windows/pwd.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/client/core/mechanisms/pwd/windows/pwmech.def b/CASA-auth-token/client/core/mechanisms/pwd/windows/pwmech.def new file mode 100644 index 00000000..0557e401 --- /dev/null +++ b/CASA-auth-token/client/core/mechanisms/pwd/windows/pwmech.def @@ -0,0 +1,10 @@ +LIBRARY PWMECH +DESCRIPTION 'CASA PW Authentication Mechanism Library.' + + +EXPORTS +; DllRegisterServer PRIVATE +; DllUnregisterServer PRIVATE +; DllGetClassObject PRIVATE + GetAuthTokenInterface PRIVATE +; DllCanUnloadNow PRIVATE \ No newline at end of file diff --git a/CASA-auth-token/client/core/test/CASA_Auth.cpp b/CASA-auth-token/client/core/test/CASA_Auth.cpp new file mode 100644 index 00000000..e78e3e4c --- /dev/null +++ b/CASA-auth-token/client/core/test/CASA_Auth.cpp @@ -0,0 +1,382 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#include "platform.h" + +// Externals +extern +char *pServerAddress; + +extern +int serverPort; + +extern +bool execHttpTest; + +extern +char serviceName[]; + +extern +char *pServiceName; + + +/*********************************************************************** + * + * EncodeData() + * + ***********************************************************************/ +int +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen) +{ + int8_t base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int retStatus; + int encodedSize; + + char *pTmp; + + // Determine the encoded size and allocate a buffer to hold the encoded data + encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4; + pTmp = (char*) malloc(encodedSize); + *ppEncodedData = pTmp; + if (*ppEncodedData) + { + uint8_t *pOut, *pIn; + int i; + + // Setup pointers to move through the buffers + pIn = (uint8_t*) pData; + pOut = (uint8_t*) *ppEncodedData; + + // Perform the encoding + for (i = 0; i < dataLen - 2; i += 3) + { + *pOut++ = base64[(pIn[i] >> 2) & 0x3F]; + *pOut++ = base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = base64[((pIn[i + 1] & 0xF) << 2) | + ((int32_t)(pIn[i + 2] & 0xC0) >> 6)]; + *pOut++ = base64[pIn[i + 2] & 0x3F]; + } + if (i < dataLen) + { + *pOut++ = base64[(pIn[i] >> 2) & 0x3F]; + if (i == (dataLen - 1)) + { + *pOut++ = base64[((pIn[i] & 0x3) << 4)]; + *pOut++ = '='; + } + else + { + *pOut++ = base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = base64[((pIn[i + 1] & 0xF) << 2)]; + } + *pOut++ = '='; + } + *pOut++ = '\0'; + + // Return the encoded data length + *pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData); + + // Success + retStatus = 0; + } + else + { + printf("-EncodeData- Buffer allocation failure\n"); + retStatus = -1; + } + + return retStatus; +} + + +/*********************************************************************** + * + * NonHttpTest() + * + ***********************************************************************/ +void NonHttpTest(void) +{ + CasaStatus retStatus; + char authToken[8192]; + int authTokenLen = sizeof(authToken); + + // Obtain an authentication token for the targeted service + retStatus = ObtainAuthToken(pServiceName, pServerAddress, authToken, &authTokenLen); + if (!CASA_SUCCESS(retStatus)) + { + printf("-NonHttpTest- ObtainAuthToken failed with status %d\n", retStatus); + } + else + { + SOCKET sock; + struct sockaddr_in localAddr = {0}; + struct sockaddr_in remoteAddr = {0}; + struct linger linger_opt = {1, 15}; + struct hostent *pLookupResult; + + printf("-NonHttpTest- ObtainAuthToken succedded, tokenlen = %d\n", authTokenLen); + + // Send the token to the server + // + // Open socket + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock != INVALID_SOCKET) + { + // Setup the local address structure + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Bind socket + if (!bind(sock, (const struct sockaddr*) &localAddr, sizeof(struct sockaddr_in))) + { + // Resolve the server address + pLookupResult = gethostbyname(pServerAddress); + if (pLookupResult) + { + // Validate the address type returned + if (pLookupResult->h_addrtype == AF_INET) + { + int numAddressesFound = 0; + + // Determine how many addresses where returned + while (pLookupResult->h_addr_list[numAddressesFound] != NULL) + { + //printf("ServerAddress = %08X\n", *((int*) pLookupResult->h_addr_list[numAddressesFound])); + numAddressesFound ++; + } + //printf("Found %d addresses\n", numAddressesFound); + + // Setup the remote address structure with the lookup results + remoteAddr.sin_family = AF_INET; + remoteAddr.sin_port = serverPort; + remoteAddr.sin_addr.s_addr = *((int*) pLookupResult->h_addr_list[0]); // Short-cut + //printf("ServerAddress = %08X\n", remoteAddr.sin_addr.s_addr); + + // Perform connect operation + if (connect(sock, + (struct sockaddr*) &remoteAddr, + sizeof(struct sockaddr_in)) == SOCKET_ERROR) + { + printf("-NonHttpTest- Connection creation failed, error = %d\n", errno); + } + else + { + // Now the connection is setup, send the credentials to the server as one line. + // using our cheesy protocol followed by a hello string. + // + // Send the token to the server (including NULL terminator) + send(sock, authToken, (int) strlen(authToken) + 1, 0); + + // Send new line + send(sock, "\n", 1, 0); + + // Send "hello" + //send(sock, helloString, strlen(helloString) + 1, MSG_NOSIGNAL); + + // Send new line + //send(sock, "\n", 1, 0); + + // Shutdown the connection + shutdown(sock, 0); + } + } + else + { + printf("-NonHttpTest- Unsupported address type returned %08X\n", pLookupResult->h_addrtype); + } + } + else + { + printf("-NonHttpTest- Lookup for %s failed\n", pServerAddress); + } + } + else + { + printf("-NonHttpTest- Unable to bind socket, error = %d", errno); + } + + // Close the socket + setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*) &linger_opt, sizeof(linger_opt)); + closesocket(sock); + } + else + { + printf("-NonHttpTest- Unable to open socket, error = %d\n", errno); + } + } +} + + +/*********************************************************************** + * + * HttpTest() + * + ***********************************************************************/ +void HttpTest(void) +{ + CasaStatus retStatus; + char authToken[4096]; + int authTokenLen = sizeof(authToken); + + // Obtain an authentication token for the targeted service + retStatus = ObtainAuthToken(pServiceName, pServerAddress, authToken, &authTokenLen); + if (!CASA_SUCCESS(retStatus)) + { + printf("-HttpTest- ObtainAuthToken failed with status %d\n", retStatus); + } + else + { + SOCKET sock; + struct sockaddr_in localAddr = {0}; + struct sockaddr_in remoteAddr = {0}; + struct linger linger_opt = {1, 15}; + struct hostent *pLookupResult; + + //printf("ObtainAuthToken succedded, token = %s\n", authToken); + printf("-HttpTest- ObtainAuthToken succedded, tokenlen = %d\n", authTokenLen); + + // Send the token to the server + // Open socket + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock != INVALID_SOCKET) + { + // Setup the local address structure + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Bind socket + if (!bind(sock, (const struct sockaddr*) &localAddr, sizeof(struct sockaddr_in))) + { + // Resolve the server address + pLookupResult = gethostbyname(pServerAddress); + if (pLookupResult) + { + // Validate the address type returned + if (pLookupResult->h_addrtype == AF_INET) + { + int numAddressesFound = 0; + + // Determine how many addresses where returned + while (pLookupResult->h_addr_list[numAddressesFound] != NULL) + { + //printf("ServerAddress = %08X\n", *((int*) pLookupResult->h_addr_list[numAddressesFound])); + numAddressesFound ++; + } + //printf("Found %d addresses\n", numAddressesFound); + + + // Setup the remote address structure with the lookup results + remoteAddr.sin_family = AF_INET; + remoteAddr.sin_port = serverPort; + remoteAddr.sin_addr.s_addr = *((int*) pLookupResult->h_addr_list[0]); // Short-cut + //printf("ServerAddress = %08X\n", remoteAddr.sin_addr.s_addr); + + // Perform connect operation + if (connect(sock, + (struct sockaddr*) &remoteAddr, + sizeof(struct sockaddr_in)) == SOCKET_ERROR) + { + printf("-HttpTest- Connection creation failed, error = %d\n", errno); + } + else + { + char *pBasicCredentials; + char *pEncodedBasicCredentials; + int encodedLength; + char CasaPrincipal[] = "CasaPrincipal:"; + char HTTPReqPart1[] = "GET /example-info HTTP/1.1\r\\nUser-Agent: CasaTestClient\r\nHost: jcstation.dnsdhcp.provo.novell.com:4096\r\nConnection: Keep-Alive\r\nAuthorization: Basic "; + + // Now the connection is setup, send 1st part of HTTP request to the server. + send(sock, HTTPReqPart1, (int) strlen(HTTPReqPart1), 0); + + // Now setup the HTTP Basic Credentials + pBasicCredentials = (char*) malloc(strlen(CasaPrincipal) + strlen(authToken) + 1); + if (pBasicCredentials) + { + memcpy(pBasicCredentials, CasaPrincipal, sizeof(CasaPrincipal)); + strcat(pBasicCredentials, authToken); + + // Now Base64 encode the credentials + if (EncodeData((const void*) pBasicCredentials, + (const int32_t) strlen(pBasicCredentials), + &pEncodedBasicCredentials, + (int32_t *) &encodedLength) == 0) + { + // Send the encoded credentials + send(sock, pEncodedBasicCredentials, encodedLength - 1, 0); + + // Send the rest of the header + send(sock, "\r\n\r\n", 4, 0); + + // Free the buffer holding the encoded credentials + free(pEncodedBasicCredentials); + } + else + { + printf("-HttpTest- Error encoding credentials\n"); + } + + // Free the buffer containing the basic credentials + free(pBasicCredentials); + } + else + { + printf("-HttpTest- Buffer allocation failure\n"); + } + + // Shutdown the connection + shutdown(sock, 0); + } + } + else + { + printf("-HttpTest- Unsupported address type returned %08X\n", pLookupResult->h_addrtype); + } + } + else + { + printf("-HttpTest- Lookup for %s failed\n", pServerAddress); + } + } + else + { + printf("-HttpTest- Unable to bind socket, error = %d", errno); + } + + // Close the socket + setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*) &linger_opt, sizeof(linger_opt)); + closesocket(sock); + } + else + { + printf("-HttpTest- Unable to open socket, error = %d\n", errno); + } + } +} diff --git a/CASA-auth-token/client/core/test/linux/main.cpp b/CASA-auth-token/client/core/test/linux/main.cpp new file mode 100644 index 00000000..a5f76009 --- /dev/null +++ b/CASA-auth-token/client/core/test/linux/main.cpp @@ -0,0 +1,171 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#include "platform.h" + + +// Extern functions +extern +void NonHttpTest(void); + +extern +void HttpTest(void); + + +// Globals +char usageString[] = "usage: test -a serverAddress -p serverPort [-s serviceName] [-h]\n"; + +char *pServerAddress = NULL; +int serverPort = 0; +bool execHttpTest = false; + +char serviceName[] = "testService"; +char *pServiceName = serviceName; + + +/*********************************************************************** + * + * dtoul() + * + ***********************************************************************/ +int +dtoul( + IN char *cp, + IN int len) +{ + int n = 0; + int i; + + for (i = 0; i < len; i++, cp++) + { + // Verify that we are dealing with a valid digit + if (*cp >= '0' && *cp <= '9') + { + n = 10 * n + (*cp - '0'); + } + else + { + printf("-dtoul- Found invalid digit\n"); + break; + } + } + + return n; +} + + +/*********************************************************************** + * + * main() + * + ***********************************************************************/ +int main(int argc, char* argv[]) +{ + // Process input parameters + int i = 1; + while(argv[i] != NULL) + { + if (strcasecmp(argv[i], "-a") == 0) + { + // Server Address option, the next argument should + // contain the address. + i++; + if (argv[i] != NULL) + { + pServerAddress = argv[i]; + } + else + { + printf(usageString); + return -1; + } + } + else if (strcasecmp(argv[i], "-p") == 0) + { + // Server port option, the next argument should + // contain the port. + i++; + if (argv[i] != NULL) + { + serverPort = htons(dtoul(argv[i], strlen(argv[i]))); + } + else + { + printf(usageString); + return -1; + } + } + else if (strcasecmp(argv[i], "-s") == 0) + { + // Service name option, the next argument should + // contain the name of the service to be targeted. + i++; + if (argv[i] != NULL) + { + pServiceName = argv[i]; + } + else + { + printf(usageString); + return -1; + } + } + else if (strcasecmp(argv[i], "-h") == 0) + { + // Perform http test option + execHttpTest = true; + } + + // Advance to the next argument + i++; + } + + // Verify that the server address and port were specified + if (pServerAddress && serverPort != 0) + { + // Repeat the test when indicated + printf("Press 'Enter' to run test or 'n + Enter' to stop.\n"); + while(getchar() != 'n') + { + // Execute the appropriate test + if (execHttpTest) + { + HttpTest(); + } + else + { + NonHttpTest(); + } + printf("Press 'Enter' to run test or 'n + Enter' to stop.\n"); + } + } + else + { + printf(usageString); + return -1; + } + + return 0; +} + diff --git a/CASA-auth-token/client/core/test/linux/make.sh b/CASA-auth-token/client/core/test/linux/make.sh new file mode 100755 index 00000000..5b915b65 --- /dev/null +++ b/CASA-auth-token/client/core/test/linux/make.sh @@ -0,0 +1,2 @@ +#!/bin/bash +g++ -o authClientTest ../CASA_Auth.cpp main.cpp -g -DN_PLAT_UNIX -I. -I../../../include -L"../../../lib/Release" -lcasa_c_authtoken -Xlinker -rpath -Xlinker ../../../lib/Release diff --git a/CASA-auth-token/client/core/test/linux/platform.h b/CASA-auth-token/client/core/test/linux/platform.h new file mode 100644 index 00000000..75c9309c --- /dev/null +++ b/CASA-auth-token/client/core/test/linux/platform.h @@ -0,0 +1,54 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "casa_c_authtoken.h" + +// +// Socket Mapping definitions +// +#undef SOCKET +#define SOCKET int +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define LINGER struct linger +#define SOCKADDR_IN struct sockaddr_in +#define closesocket close + diff --git a/CASA-auth-token/client/core/test/windows/main.cpp b/CASA-auth-token/client/core/test/windows/main.cpp new file mode 100644 index 00000000..65ab2b6c --- /dev/null +++ b/CASA-auth-token/client/core/test/windows/main.cpp @@ -0,0 +1,187 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#include "platform.h" + +// Extern functions +extern +void NonHttpTest(void); + +extern +void HttpTest(void); + + +// Globals +char usageString[] = "usage: test -a serverAddress -p serverPort [-s serviceName] [-h]\n"; + +char *pServerAddress = NULL; +int serverPort = 0; +BOOLEAN execHttpTest = FALSE; + +char serviceName[] = "testService"; +char *pServiceName = serviceName; + + +/*********************************************************************** + * + * dtoul() + * + ***********************************************************************/ +int +dtoul( + IN char *cp, + IN int len) +{ + int n = 0; + int i; + + for (i = 0; i < len; i++, cp++) + { + // Verify that we are dealing with a valid digit + if (*cp >= '0' && *cp <= '9') + { + n = 10 * n + (*cp - '0'); + } + else + { + printf("-dtoul- Found invalid digit\n"); + break; + } + } + + return n; +} + + + + +/*********************************************************************** + * + * main() + * + ***********************************************************************/ +int main(int argc, char* argv[]) +{ + // Process input parameters + int i = 1; + while(argv[i] != NULL) + { + if (stricmp(argv[i], "-a") == 0) + { + // Server Address option, the next argument should + // contain the address. + i++; + if (argv[i] != NULL) + { + pServerAddress = argv[i]; + } + else + { + printf(usageString); + return -1; + } + } + else if (stricmp(argv[i], "-p") == 0) + { + // Server port option, the next argument should + // contain the port. + i++; + if (argv[i] != NULL) + { + serverPort = htons(dtoul(argv[i], (int) strlen(argv[i]))); + } + else + { + printf(usageString); + return -1; + } + } + else if (stricmp(argv[i], "-s") == 0) + { + // Service name option, the next argument should + // contain the name of the service to be targeted. + i++; + if (argv[i] != NULL) + { + pServiceName = argv[i]; + } + else + { + printf(usageString); + return -1; + } + } + else if (stricmp(argv[i], "-h") == 0) + { + // Perform http test option + execHttpTest = TRUE; + } + + // Advance to the next argument + i++; + } + + // Verify that the server address and port were specified + if (pServerAddress && serverPort != 0) + { + int winsockStartupResult; + WSADATA winsockData; + + // First initialize winsock + if ((winsockStartupResult = WSAStartup(MAKEWORD(2,2), &winsockData)) == 0) + { + // Repeat the test when indicated + printf("Press 'Enter' to run test or 'n + Enter' to stop.\n"); + while(getchar() != 'n') + { + // Execute the appropriate test + if (execHttpTest) + { + HttpTest(); + } + else + { + NonHttpTest(); + } + printf("Press 'Enter' to run test or 'n + Enter' to stop.\n"); + } + + // Close winsock + WSACleanup(); + } + else + { + printf("-main- WSAStartup failed, error = %d\n", winsockStartupResult); + } + } + else + { + printf(usageString); + return -1; + } + + return 0; +} + + diff --git a/CASA-auth-token/client/core/test/windows/platform.h b/CASA-auth-token/client/core/test/windows/platform.h new file mode 100644 index 00000000..be4b3d33 --- /dev/null +++ b/CASA-auth-token/client/core/test/windows/platform.h @@ -0,0 +1,29 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#include +#include +#include "casa_c_authtoken.h" + +//#define errno WSAGetLastError() diff --git a/CASA-auth-token/client/core/test/windows/test.vcproj b/CASA-auth-token/client/core/test/windows/test.vcproj new file mode 100644 index 00000000..bf016d2e --- /dev/null +++ b/CASA-auth-token/client/core/test/windows/test.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/client/core/util.c b/CASA-auth-token/client/core/util.c new file mode 100644 index 00000000..b93a5508 --- /dev/null +++ b/CASA-auth-token/client/core/util.c @@ -0,0 +1,321 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Tables for Base64 encoding and decoding +static const int8_t g_Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const uint8_t g_Expand64[256] = +{ + /* ASCII table */ + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 +}; + + +//++======================================================================= +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int encodedSize; + + char *pTmp; + + DbgTrace(3, "-EncodeData- Start\n", 0); + + // Determine the encoded size and allocate a buffer to hold the encoded data + encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4; + pTmp = (char*) malloc(encodedSize); + *ppEncodedData = pTmp; + if (*ppEncodedData) + { + uint8_t *pOut, *pIn; + int i; + + // Setup pointers to move through the buffers + pIn = (uint8_t*) pData; + pOut = (uint8_t*) *ppEncodedData; + + // Perform the encoding + for (i = 0; i < dataLen - 2; i += 3) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) | + ((int32_t)(pIn[i + 2] & 0xC0) >> 6)]; + *pOut++ = g_Base64[pIn[i + 2] & 0x3F]; + } + if (i < dataLen) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + if (i == (dataLen - 1)) + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4)]; + *pOut++ = '='; + } + else + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)]; + } + *pOut++ = '='; + } + *pOut++ = '\0'; + + // Return the encoded data length + *pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int i, j; + int decodedSize; + + DbgTrace(3, "-DecodeData- Start\n", 0); + + // Determine the decoded size + for (i = 0, j = 0; i < encodedDataLen; i++) + if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64) + j++; + decodedSize = (j * 3 + 3) / 4; + + // Allocate buffer to hold the decoded data + *ppData = malloc(decodedSize); + if (*ppData) + { + bool endReached = false; + uint8_t c0, c1, c2, c3; + uint8_t *p, *q; + + // Initialize parameters that will be used during the decode operation + c0 = c1 = c2 = c3 = 0; + p = (uint8_t*) pEncodedData; + q = (uint8_t*) *ppData; + + // Decode the data + // + // Loop through the data, piecing back information. Any newlines, and/or + // carriage returns need to be skipped. + while (j > 4) + { + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + endReached = true; + break; + } + c0 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2); + j--; + endReached = true; + break; + } + c1 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4); + j -= 2; + endReached = true; + break; + } + c2 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6); + j -= 3; + endReached = true; + break; + } + c3 = *(p++); + + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]); + j -= 4; + } + if (!endReached) + { + if (j > 1) + *(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4); + if (j > 2) + *(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2); + if (j > 3) + *(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]); + } + + // Return the length of the decoded data + *pDataLen = (int32_t)(q - (uint8_t*)*ppData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +dtoul( + IN const char *cp, + IN const int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int n = 0; + int i; + + DbgTrace(2, "-dtoul- Start\n", 0); + + for (i = 0; i < len; i++, cp++) + { + // Verify that we are dealing with a valid digit + if (*cp >= '0' && *cp <= '9') + { + n = 10 * n + (*cp - '0'); + } + else + { + DbgTrace(0, "-dtoul- Found invalid digit\n", 0); + break; + } + } + + DbgTrace(2, "-dtoul- End, result = %d\n", n); + + return n; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/windows/Makefile.am b/CASA-auth-token/client/core/windows/Makefile.am new file mode 100644 index 00000000..4f0e0673 --- /dev/null +++ b/CASA-auth-token/client/core/windows/Makefile.am @@ -0,0 +1,69 @@ +####################################################################### +# +# Copyright (C) 2004 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: Greg Richardson +# +####################################################################### + +SUBDIRS = + +DIST_SUBDIRS = + +EXTRA_DIST = client.vcproj ../*.c *.c *.h *.def + +if DEBUG +TARGET_CFG = Debug +else +TARGET_CFG = Release +endif + +PACKAGE = client +TARGET_FILE = authtoken.dll +LOG_FILE = $(PACKAGE).log + +all-am: $(TARGET_FILE) + +.PHONY: $TARGET_FILE) devenv + +devenv: + @if ! test -x "$(VSINSTALLDIR)/devenv.exe"; then echo "Error: Microsoft Visual Studio .NET is currently required to build MSI and MSM packages"; exit 1; fi + +$(TARGET_FILE): devenv + @rm -f $(LOG_FILE) $@ + @CMD='"$(VSINSTALLDIR)/devenv.exe" ../../auth.sln /build $(TARGET_CFG) /project $(PACKAGE) /out $(LOG_FILE)'; \ + echo $$CMD; \ + if eval $$CMD; then \ + ls -l $(TARGET_CFG)/$(TARGET_FILE); \ + else \ + grep -a "ERROR:" $(LOG_FILE); \ + fi + +package-clean clean-local: + rm -rf Release/* Release Debug/* Debug*/Release */Debug *.log *.suo + +clean: + rm -rf Release/* Release Debug/* Debug */Release */Debug *.log *.suo + +distclean-local: package-clean + rm -f Makefile + +maintainer-clean-local: + rm -f Makefile.in + + + diff --git a/CASA-auth-token/client/core/windows/authtoken.def b/CASA-auth-token/client/core/windows/authtoken.def new file mode 100644 index 00000000..d0c062b8 --- /dev/null +++ b/CASA-auth-token/client/core/windows/authtoken.def @@ -0,0 +1,11 @@ +LIBRARY AUTHTOKEN +DESCRIPTION 'CASA Authentication Token Library.' + + +EXPORTS +; DllRegisterServer PRIVATE +; DllUnregisterServer PRIVATE +; DllGetClassObject PRIVATE + ObtainAuthToken PRIVATE + ObtainAuthTokenEx PRIVATE +; DllCanUnloadNow PRIVATE \ No newline at end of file diff --git a/CASA-auth-token/client/core/windows/client.vcproj b/CASA-auth-token/client/core/windows/client.vcproj new file mode 100644 index 00000000..96c989d3 --- /dev/null +++ b/CASA-auth-token/client/core/windows/client.vcproj @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/client/core/windows/dllsup.c b/CASA-auth-token/client/core/windows/dllsup.c new file mode 100644 index 00000000..a0726f5d --- /dev/null +++ b/CASA-auth-token/client/core/windows/dllsup.c @@ -0,0 +1,233 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" +#include +#include +#include "casa_c_authtoken_ex.h" + +//===[ External data ]===================================================== +extern +char clientConfigFolderPartialPath[]; + +extern +char mechConfigFolderPartialPath[]; + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +UINT32 g_ulCount = 0; +UINT32 g_ulLock = 0; +HANDLE g_hModule; +HANDLE g_hModuleMutex; + + +//++======================================================================= +CasaStatus SSCS_CALL +ObtainAuthTokenEx( + IN const char *pServiceName, + IN const char *pHostName, + INOUT char *pAuthTokenBuf, + INOUT int *pAuthTokenBufLen, + IN void *pCredStoreScope) +// +// Arguments: +// pServiceName - +// Pointer to NULL terminated string that contains the +// name of the service to which the client is trying to +// authenticate. +// +// pHostName - +// Pointer to NULL terminated string that contains the +// name of the host where resides the service to which the +// client is trying to authenticate. Note that the name +// can either be a DNS name or a dotted IP address. +// +// pAuthTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pAuthTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pAuthTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pAuthTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pAuthTokenBuf is +// not large enough. +// +// pCredStoreScope - +// Pointer to CASA structure for scoping credential store access +// to specific users. This can only be leveraged by applications +// running in the context of System. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified +// service at host. The user is scoped using the info associated +// with the magic cookie. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + + DbgTrace(1, "-ObtainAuthTokenEx- Start\n", 0); + + // Call our internal worker + retStatus = ObtainAuthTokenInt(pServiceName, + pHostName, + pAuthTokenBuf, + pAuthTokenBufLen, + pCredStoreScope); + + DbgTrace(1, "-ObtainAuthTokenEx- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +BOOL APIENTRY DllMain( + HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +//=======================================================================-- +{ + BOOL retStatus = TRUE; + char programFilesFolder[MAX_PATH]; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + g_hModule = hModule; + + // Setup the path to the client and auth mechanisms config folders + if (SHGetFolderPath(NULL, + CSIDL_PROGRAM_FILES, + NULL, + 0, + programFilesFolder) == 0) + { + strcpy(clientConfigFolder, programFilesFolder); + PathAppend(clientConfigFolder, clientConfigFolderPartialPath); + + strcpy(mechConfigFolder, programFilesFolder); + PathAppend(mechConfigFolder, mechConfigFolderPartialPath); + + // Allocate module mutex + g_hModuleMutex = CreateMutex(NULL, FALSE, NULL); + if (! g_hModuleMutex) + { + // Module initialization failed + OutputDebugString("CASAAUTH -DllMain- Failed to create mutex\n"); + retStatus = FALSE; + } + } + else + { + // Failed to obtain the Program Files path + OutputDebugString("CASAAUTH -DllMain- Failed to obtain the Program Files path\n"); + retStatus = FALSE; + } + + break; + } + + case DLL_THREAD_ATTACH: + { + g_hModule = hModule; + break; + } + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + { + /* Don't uninitialize on windows + tbd + */ + break; + } + } + + return retStatus; +} + +//++======================================================================= +// +// DllCanUnloadNow +// +// Synopsis +// +// +STDAPI +DllCanUnloadNow() +// +// Input Arguments +// +// Ouput Arguments +// +// Return Value +// S_OK The DLL can be unloaded. +// S_FALSE The DLL cannot be unloaded now. +// +// Description +// An Exported Function. +// DLLs that support the OLE Component Object Model (COM) should implement +// and export DllCanUnloadNow. +// A call to DllCanUnloadNow determines whether the DLL from which it is +// exported is still in use. A DLL is no longer in use when it is not +// managing any existing objects (the reference count on all of its objects +// is 0). +// DllCanUnloadNow returns S_FALSE if there are any existing references to +// objects that the DLL manages. +// +// Environment +// +// See Also +// +//=======================================================================-- +{ + // tbd + return ((g_ulCount == 0 && g_ulLock == 0) ? S_OK : S_FALSE); +} + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/client/core/windows/platform.c b/CASA-auth-token/client/core/windows/platform.c new file mode 100644 index 00000000..25f2a1c5 --- /dev/null +++ b/CASA-auth-token/client/core/windows/platform.c @@ -0,0 +1,580 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// Normalized Host Name Cache Entry definition +// +typedef struct _NormalizedHostNameCacheEntry +{ + LIST_ENTRY listEntry; + char *pHostName; + char *pNormalizedHostName; + int buffLengthRequired; + +} NormalizedHostNameCacheEntry, *PNormalizedHostNameCacheEntry; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Normalized host name cache list head +static +LIST_ENTRY normalizedHostNameCacheListHead; + +// Synchronization mutex for the normalized host name cache +static +HANDLE hNormalizedHostNameCacheMutex; + +// Client configuration file folder +char clientConfigFolder[MAX_PATH]; +char clientConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth"; + +// Authentication mechanism configuration file folder +char mechConfigFolder[MAX_PATH]; +char mechConfigFolderPartialPath[] = "Novell\\Casa\\Etc\\Auth\\Mechanisms"; + +// Path separator +char pathCharString[] = "\\"; + +//++======================================================================= +CasaStatus +CreateUserMutex( + HANDLE *phMutex + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + char *pUsername = NULL; + DWORD nameLength = 0; + + DbgTrace(1, "-CreateUserMutex- Start\n", 0); + + // Get the size of the buffer required to obtain the user name + GetUserName(pUsername, &nameLength); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + // Allocate buffer to hold the user name + pUsername = (char*) malloc(nameLength); + if (pUsername) + { + // Get the name of the user + if (GetUserName(pUsername, &nameLength)) + { + SECURITY_ATTRIBUTES mutexAttributes; + char mutexName[256]; + + // Now lets create a global semaphore for the + // user and allow its handle to be inherited. + mutexAttributes.nLength = sizeof(mutexAttributes); + mutexAttributes.lpSecurityDescriptor = NULL; + mutexAttributes.bInheritHandle = TRUE; + if (sprintf(mutexName, "Global\\CASA_Auth_Mutex_%s", pUsername) != -1) + { + *phMutex = CreateMutex(&mutexAttributes, + FALSE, + mutexName); + if (*phMutex == NULL) + { + DbgTrace(0, "-CreateUserMutex- CreateMutex failed, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-CreateUserMutex- GetUserName failed, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Free the buffer allocated to hold the user name + free(pUsername); + } + else + { + DbgTrace(0, "-CreateUserMutex- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-CreateUserMutex- Unexpected GetUserName error, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + DbgTrace(1, "-CreateUserMutex- End, retStatus\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +AcquireUserMutex( + HANDLE hMutex + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-AcquireUserMutex- Start\n", 0); + + WaitForSingleObject(hMutex, INFINITE); + + DbgTrace(2, "-AcquireUserMutex- End\n", 0); +} + + +//++======================================================================= +void +ReleaseUserMutex( + HANDLE hMutex + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-ReleaseUserMutex- Start\n", 0); + + if (ReleaseMutex(hMutex) == 0) + { + DbgTrace(0, "-ReleaseUserMutex- ReleaseMutex failed, error = %d\n", GetLastError()); + } + + DbgTrace(2, "-ReleaseUserMutex- End\n", 0); +} + + +//++======================================================================= +void +DestroyUserMutex( + HANDLE hMutex + ) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-DestroyUserMutex- Start\n", 0); + + if (CloseHandle(hMutex) == 0) + { + DbgTrace(0, "-DestroyUserMutex- CloseHandle failed, error = %d\n", GetLastError()); + } + + DbgTrace(2, "-DestroyUserMutex- End\n", 0); +} + + +//++======================================================================= +LIB_HANDLE +OpenLibrary( + IN char *pFileName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + LIB_HANDLE libHandle; + + DbgTrace(1, "-OpenLibrary- Start\n", 0); + + libHandle = LoadLibrary(pFileName); + if (libHandle == NULL) + { + DbgTrace(0, "-OpenLibrary- Not able to load library, error = %d\n", GetLastError()); + } + + DbgTrace(1, "-OpenLibrary- End, handle = %08X\n", libHandle); + + return libHandle; +} + + +//++======================================================================= +void +CloseLibrary( + IN LIB_HANDLE libHandle) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-CloseLibrary- Start\n", 0); + + FreeLibrary(libHandle); + + DbgTrace(1, "-CloseLibrary- End\n", 0); +} + + +//++======================================================================= +void* +GetFunctionPtr( + IN LIB_HANDLE libHandle, + IN char *pFunctionName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + void *pFuncPtr; + + DbgTrace(1, "-GetFunctionPtr- Start\n", 0); + + pFuncPtr = GetProcAddress(libHandle, pFunctionName); + if (pFuncPtr == NULL) + { + DbgTrace(0, "-GetFunctionPtr- Not able to obtain func ptr, error = %d\n", GetLastError()); + } + + DbgTrace(1, "-GetFunctionPtr- End, pFuncPtr = %08X\n", pFuncPtr); + + return pFuncPtr; +} + + +//++======================================================================= +char* +NormalizeHostName( + IN const char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pNormalizedName = NULL; + LIST_ENTRY *pListEntry; + NormalizedHostNameCacheEntry *pEntry = NULL; + + DbgTrace(1, "-NormalizeHostName- Start\n", 0); + + // Obtain our synchronization mutex + WaitForSingleObject(hNormalizedHostNameCacheMutex, INFINITE); + + // First try to find an entry in the normalized host name cache + // for the host name provided. + pListEntry = normalizedHostNameCacheListHead.Flink; + while (pListEntry != &normalizedHostNameCacheListHead) + { + // Get pointer to the entry + pEntry = CONTAINING_RECORD(pListEntry, NormalizedHostNameCacheEntry, listEntry); + + // Check if the entry is for the host name + if (strcmp(pHostName, pEntry->pHostName) == 0) + { + // This entry corresponds to the given host name + break; + } + else + { + // The entry does not correspond to the given host name + pEntry = NULL; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Check if we found an entry in our cache for the given host name + if (pEntry) + { + // Entry found, obtain the normalized name from it. + pNormalizedName = (char*) malloc(pEntry->buffLengthRequired); + if (pNormalizedName) + { + // Copy the normalized name onto the allocated buffer + strcpy(pNormalizedName, pEntry->pNormalizedHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + // An entry was not found in our cache, create one. + pEntry = (NormalizedHostNameCacheEntry*) malloc(sizeof(NormalizedHostNameCacheEntry)); + if (pEntry) + { + // Zero the entry + memset(pEntry, 0, sizeof(*pEntry)); + + // Allocate a buffer to hold the host name in the entry + pEntry->pHostName = (char*) malloc(strlen(pHostName) + 1); + if (pEntry->pHostName) + { + struct hostent *pLookupResult; + struct sockaddr_in sockAddr = {0}; + + // Copy the host name given into the allocated buffer + strcpy(pEntry->pHostName, pHostName); + + // Now try to resolve the normalized name + pLookupResult = gethostbyname(pHostName); + if (pLookupResult && pLookupResult->h_addrtype == AF_INET) + { + char dnsHostName[NI_MAXHOST]; + + // Set up a sockaddr structure + sockAddr.sin_family = AF_INET; + sockAddr.sin_addr.S_un.S_addr = *((int*) pLookupResult->h_addr_list[0]); + + // Now try to resolve the name using DNS + if (getnameinfo((const struct sockaddr*) &sockAddr, + sizeof(sockAddr), + dnsHostName, + sizeof(dnsHostName), + NULL, + 0, + NI_NAMEREQD) == 0) + { + // We resolved the address to a DNS name, use it as the normalized name. + pEntry->buffLengthRequired = (int) strlen(dnsHostName) + 1; + pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); + if (pEntry->pNormalizedHostName) + { + // Copy the dns name + strcpy(pEntry->pNormalizedHostName, dnsHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", WSAGetLastError()); + + // Not able to resolve the name in DNS, just use the host name as + // the normalized name. + pEntry->buffLengthRequired = (int) strlen(pHostName) + 1; + pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); + if (pEntry->pNormalizedHostName) + { + // Copy the host name + strcpy(pEntry->pNormalizedHostName, pHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Name resolution failed, error = %d\n", WSAGetLastError()); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + + // Free the space allocated for the entry + free(pEntry); + } + + // Proceed based on whether or not we normalized the name + if (pEntry->pNormalizedHostName) + { + // The name was normalized, save the entry in our cache. + InsertHeadList(&normalizedHostNameCacheListHead, &pEntry->listEntry); + + // Return the normalized name present in the entry + pNormalizedName = (char*) malloc(pEntry->buffLengthRequired); + if (pNormalizedName) + { + // Copy the normalized name onto the allocated buffer + strcpy(pNormalizedName, pEntry->pNormalizedHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + // The host name was not normalized, free allocated resources. + if (pEntry->pHostName) + free(pEntry->pHostName); + free(pEntry); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + + // Release our synchronization mutex + if (ReleaseMutex(hNormalizedHostNameCacheMutex) == 0) + { + DbgTrace(0, "-NormalizeHostName- ReleaseMutex failed, error\n", 0); + } + + DbgTrace(1, "-NormalizeHostName- End, pNormalizedName = %08X\n", pNormalizedName); + + return pNormalizedName; +} + + +//++======================================================================= +CasaStatus +InitializeHostNameNormalization(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + int winsockStartupResult; + WSADATA winsockData; + + DbgTrace(1, "-InitializeHostNameNormalization- Start\n", 0); + + // Initialize winsock + if ((winsockStartupResult = WSAStartup(MAKEWORD(2,2), &winsockData)) == 0) + { + // Initialize the cache list head + InitializeListHead(&normalizedHostNameCacheListHead); + + // Create a cache mutex only applicable to the current process + hNormalizedHostNameCacheMutex = CreateMutex(NULL, + FALSE, + NULL); + if (hNormalizedHostNameCacheMutex != NULL) + { + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-InitializeHostNameNormalization- CreateMutex failed, error = %d\n", GetLastError()); + } + } + else + { + DbgTrace(0, "-InitializeHostNameNormalization- WSAStartup failed, error = %d\n", winsockStartupResult); + } + + DbgTrace(1, "-InitializeHostNameNormalization- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/core/windows/platform.h b/CASA-auth-token/client/core/windows/platform.h new file mode 100644 index 00000000..c4b03732 --- /dev/null +++ b/CASA-auth-token/client/core/windows/platform.h @@ -0,0 +1,103 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +//#define DbgTrace(LEVEL, X, Y) { \ +//char printBuff[256]; \ +// if (LEVEL == 0 || DebugLevel >= LEVEL) \ +// { \ +// _snprintf(printBuff, sizeof(printBuff), X, Y); \ +// printf("CASA_AuthToken %s", printBuff); \ +// } \ +//} +#define DbgTrace(LEVEL, X, Y) { \ +char formatBuff[128]; \ +char printBuff[256]; \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + strcpy(formatBuff, "CASA_AuthToken "); \ + strncat(formatBuff, X, sizeof(formatBuff) - 10); \ + _snprintf(printBuff, sizeof(printBuff), formatBuff, Y); \ + OutputDebugString(printBuff); \ + } \ +} + +// +// Rpc Session definition +// +typedef struct _RpcSession +{ + HINTERNET hSession; + HINTERNET hConnection; + char *pHostName; + +} RpcSession, *PRpcSession; + + +// +// Other definitions +// +#define LIB_HANDLE HMODULE +#define bool BOOLEAN +#define true TRUE +#define false FALSE + +#define AcquireModuleMutex WaitForSingleObjectEx(g_hModuleMutex, INFINITE, FALSE) +#define ReleaseModuleMutex ReleaseMutex(g_hModuleMutex) + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + +//===[ External data ]===================================================== + +extern HANDLE g_hModuleMutex; + +//========================================================================= + diff --git a/CASA-auth-token/client/core/windows/rpc.c b/CASA-auth-token/client/core/windows/rpc.c new file mode 100644 index 00000000..e792a883 --- /dev/null +++ b/CASA-auth-token/client/core/windows/rpc.c @@ -0,0 +1,799 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +#define INITIAL_RESPONSE_DATA_BUF_SIZE 1028 +#define INCREMENT_RESPONSE_DATA_BUF_SIZE 256 + +#define MAX_RPC_RETRIES 3 + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//++======================================================================= +static +CasaStatus +CopyMultiToWideAlloc( + IN char *pMulti, + IN int multiSize, + INOUT LPWSTR *ppWide, + INOUT int *pWideSize) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus; + int size, i; + + DbgTrace(2, "-CopyMultiToWideAlloc- Start\n", 0); + + size = (multiSize + 1) * sizeof(WCHAR); + + if ((*ppWide = (PWCHAR) malloc(size)) != NULL) + { + for (i = 0; i < multiSize; i++) + { + *(*ppWide + i) = (unsigned char) *(pMulti + i); + } + + *(*ppWide + i) = L'\0'; + + if (pWideSize) + { + *pWideSize = size - sizeof(WCHAR); + } + + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(2, "-CopyMultiToWideAlloc- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus +CopyWideToMultiAlloc( + IN LPWSTR pWide, + IN int wideSize, + INOUT char **ppMulti, + INOUT int *pMultiSize) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus; + int size, i; + + DbgTrace(2, "-CopyWideToMultiAlloc- Start\n", 0); + + size = wideSize + 1; + + if ((*ppMulti = malloc(size)) != NULL) + { + for (i = 0; i < wideSize; i++) + { + *(*ppMulti + i) = (char) *(pWide + i); + } + + *(*ppMulti + i) = '\0'; + + if (pMultiSize) + { + *pMultiSize = size - 1; + } + + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(2, "-CopyWideToMultiAlloc- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +RpcSession* +OpenRpcSession( + IN char *pHostName, + IN uint16_t hostPort) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + RpcSession *pSession; + bool success = false; + + DbgTrace(1, "-OpenRpcSession- Start\n", 0); + + // Allocate space for the session + pSession = (RpcSession*) malloc(sizeof(*pSession)); + if (pSession) + { + // Zero the session structure + memset(pSession, 0, sizeof(*pSession)); + + // Save copy of the hostname + pSession->pHostName = malloc(strlen(pHostName) + 1); + if (pSession->pHostName) + { + strcpy(pSession->pHostName, pHostName); + + // Open a Winhttp session + pSession->hSession = WinHttpOpen(L"CASA Client/1.0", + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, + 0); + if (pSession->hSession) + { + LPWSTR pWideHostName; + int wideHostLen; + + // Session opened, now convert the host name to Unicode so that + // we can open a connection. + if (CopyMultiToWideAlloc(pHostName, + (int) strlen(pHostName), + &pWideHostName, + &wideHostLen) == CASA_STATUS_SUCCESS) + { + // Now open connection + pSession->hConnection = WinHttpConnect(pSession->hSession, + pWideHostName, + hostPort, + 0); + if (pSession->hConnection == NULL) + { + DbgTrace(0, "-OpenRpcSession- Failed to open connection, error = %d\n", GetLastError()); + } + else + { + success = true; + } + + // Free the host name wide string buffer + free(pWideHostName); + } + else + { + DbgTrace(0, "-OpenRpcSession- Error converting host name to wide string\n", 0); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to open session, error = %d\n", GetLastError()); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for host name\n", 0); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for rpc session\n", 0); + } + + // Clean up if we did not succeed + if (!success) + { + if (pSession) + { + if (pSession->hConnection) + WinHttpCloseHandle(pSession->hConnection); + + if (pSession->hSession) + WinHttpCloseHandle(pSession->hSession); + + if (pSession->pHostName) + free(pSession->pHostName); + + free(pSession); + pSession = NULL; + } + } + + DbgTrace(2, "-OpenRpcSession- End, pSession = %08X\n", pSession); + + return pSession; +} + + +//++======================================================================= +void +CloseRpcSession( + IN RpcSession *pSession) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-CloseRpcSession- Start\n", 0); + + // Close the connection handle + WinHttpCloseHandle(pSession->hConnection); + + // Close the session handle + WinHttpCloseHandle(pSession->hSession); + + // Free hostname buffer if necessary + if (pSession->pHostName) + free(pSession->pHostName); + + // Free the space allocated for the session + free(pSession); + + DbgTrace(1, "-CloseRpcSession- End\n", 0); +} + + +//++======================================================================= +static +void CALLBACK +SecureFailureStatusCallback( + IN HINTERNET hRequest, + IN DWORD *pContext, + IN DWORD internetStatus, + IN LPVOID pStatusInformation, + IN DWORD statusInformationLength) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(1, "-SecureFailureStatusCallback- Start\n", 0); + + // Only deal with failures related to certificates + if (internetStatus == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) + { + // Save the specific failure status + *pContext = *(DWORD*) pStatusInformation; + } + + DbgTrace(1, "-SecureFailureStatusCallback- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +InternalRpc( + IN RpcSession *pSession, + IN char *pMethod, + IN long flags, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ +#define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated + + CasaStatus retStatus = CASA_STATUS_SUCCESS; + char rpcTarget[256]; + LPWSTR pWideRpcTarget; + int wideRpcTargetLen; + WCHAR sendHeaders[] = L"Content-Type: text/html"; + DWORD securityFailureStatusFlags; + int retriesAllowed = 1; + bool attemptRetry; + + DbgTrace(1, "-InternalRpc- Start\n", 0); + + // Initialize output parameter + *ppResponseData = NULL; + + // Create rpc target string and convert it to a wide string + sprintf(rpcTarget, "CasaAuthTokenSvc/Rpc?method=%s", pMethod); + retStatus = CopyMultiToWideAlloc(rpcTarget, + (int) strlen(rpcTarget), + &pWideRpcTarget, + &wideRpcTargetLen); + if (CASA_SUCCESS(retStatus)) + { + HINTERNET hRequest; + + do + { + // Forget about having been told to retry + attemptRetry = false; + + // Open a request handle + hRequest = WinHttpOpenRequest(pSession->hConnection, + L"POST", + pWideRpcTarget, + NULL, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + flags & SECURE_RPC_FLAG? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH); + if (hRequest) + { + int reqDataLen = (int) strlen(pRequestData); + + // Check if we need to set options to deal with secure connections + if (flags & SECURE_RPC_FLAG) + { + // We are using secure connections, now proceed based on whether or not + // we are configured to allow invalid certificates. + if (flags & ALLOW_INVALID_CERTS_RPC_FLAG + || (flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG + && InvalidCertsFromHostAllowed(pSession->pHostName))) + { + DWORD secFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA; + + // We are configured to allow invalid certificates, inform the HTTP stack. + if (WinHttpSetOption(hRequest, + WINHTTP_OPTION_SECURITY_FLAGS, + &secFlags, + sizeof(secFlags)) == FALSE) + { + DbgTrace(0, "-InternalRpc- Failed setting options to ignore invalid certs, error = %d\n", GetLastError()); + } + } + else + { + // We are not configured to allow invalid certificates, set a callback handler + // to detect invalid certificate conditions. + if (WinHttpSetStatusCallback(hRequest, + SecureFailureStatusCallback, + WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, + (DWORD_PTR) NULL) == WINHTTP_INVALID_STATUS_CALLBACK) + { + DbgTrace(0, "-InternalRpc- Failed setting status callback, error = %d\n", GetLastError()); + } + } + } + + // Send the request + securityFailureStatusFlags = 0; + if (WinHttpSendRequest(hRequest, + sendHeaders, + -1, + pRequestData, + reqDataLen, + reqDataLen, + (DWORD_PTR) &securityFailureStatusFlags)) + { + // Request sent, now await for the response. + if (WinHttpReceiveResponse(hRequest, NULL)) + { + WCHAR httpCompStatus[4] = {0}; + DWORD httpCompStatusLen = sizeof(httpCompStatus); + + // Response received, make sure that it completed successfully. + if (WinHttpQueryHeaders(hRequest, + WINHTTP_QUERY_STATUS_CODE, + NULL, + &httpCompStatus, + &httpCompStatusLen, + WINHTTP_NO_HEADER_INDEX)) + { + // Check that the request completed successfully + if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0) + { + char *pResponseData; + int responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE; + int responseDataRead = 0; + + // Now read the response data, to do so we need to allocate a buffer. + pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE); + if (pResponseData) + { + char *pCurrLocation = pResponseData; + DWORD bytesRead; + + do + { + bytesRead = 0; + if (WinHttpReadData(hRequest, + (LPVOID) pCurrLocation, + responseDataBufSize - responseDataRead, + &bytesRead)) + { + pCurrLocation += bytesRead; + responseDataRead += bytesRead; + + // Check if we need to allocate a larger buffer + if (responseDataRead == responseDataBufSize) + { + char *pTmpBuf; + + // We need to upgrade the receive buffer + pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE); + if (pTmpBuf) + { + memcpy(pTmpBuf, pResponseData, responseDataBufSize); + free(pResponseData); + pResponseData = pTmpBuf; + pCurrLocation = pResponseData + responseDataBufSize; + responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE; + } + else + { + DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + } + else + { + DbgTrace(0, "-InternalRpc- Failed reading response data, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } while (CASA_SUCCESS(retStatus) + && bytesRead != 0); + + // Check if the response data was successfully received + if (CASA_SUCCESS(retStatus)) + { + // The response data was received, return it to the caller. + *ppResponseData = pResponseData; + *pResponseDataLen = responseDataRead; + } + else + { + // Failed to receive the response data, free the allocated buffer. + free(pResponseData); + } + } + else + { + DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %S\n", httpCompStatus); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-InternalRpc- Unable to obtain http request completion status, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-InternalRpc- Unable to receive response, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + int error = GetLastError(); + + if (error == ERROR_WINHTTP_CANNOT_CONNECT) + { + DbgTrace(0, "-InternalRpc- Unable to connect to server\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_AUTH_SERVER_UNAVAILABLE); + } + else if (error == ERROR_WINHTTP_SECURE_FAILURE) + { + DbgTrace(1, "-InternalRpc- Secure connection failure, flags = %0x\n", securityFailureStatusFlags); + + // Try to deal with the issue + if ((securityFailureStatusFlags & ~(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA + | WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID + | WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)) == 0 + && flags & ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG) + { + WINHTTP_CERTIFICATE_INFO certInfo; + DWORD certInfoLen = sizeof(certInfo); + + // The failure was due to an invalid CN, CA, or both. + // + // Obtain information about the server certificate to give user + // the choice of accepting it. + if (WinHttpQueryOption(hRequest, + WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, + &certInfo, + &certInfoLen) + && certInfo.lpszSubjectInfo != NULL + && certInfo.lpszIssuerInfo != NULL) + { + char *pSubjectInfo; + int subjectInfoLen; + + // Convert the subjectInfo to multi-byte + retStatus = CopyWideToMultiAlloc(certInfo.lpszSubjectInfo, + (int) wcslen(certInfo.lpszSubjectInfo), + &pSubjectInfo, + &subjectInfoLen); + if (CASA_SUCCESS(retStatus)) + { + char *pIssuerInfo; + int issuerInfoLen; + + // Convert the issuerInfo to multi-byte + retStatus = CopyWideToMultiAlloc(certInfo.lpszIssuerInfo, + (int) wcslen(certInfo.lpszIssuerInfo), + &pIssuerInfo, + &issuerInfoLen); + if (CASA_SUCCESS(retStatus)) + { + long invalidCertFlags = 0; + + // Setup the invalid cert flags + if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA) + invalidCertFlags |= INVALID_CERT_CA_FLAG; + + if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID) + invalidCertFlags |= INVALID_CERT_CN_FLAG; + + if (securityFailureStatusFlags & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID) + invalidCertFlags |= INVALID_CERT_DATE_FLAG; + + // Give user the choice to accept the certificate + if (UserApprovedCert(pSession->pHostName, + pSubjectInfo, + pIssuerInfo, + invalidCertFlags)) + { + DbgTrace(1, "-InternalRpc- User approved invalid certificate from %s\n", pSession->pHostName); + + // tbd - Investigate if there is a way to set the accepted certificate in a store so that + // it can be utilized by the SSL stack directly. This would be a better method for dealing with + // this issue. + + AllowInvalidCertsFromHost(pSession->pHostName); + + // Try to retry the request + attemptRetry = true; + } + else + { + DbgTrace(1, "-InternalRpc- User did not approve invalid certificate from %s\n", pSession->pHostName); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_SERVER_CERTIFICATE); + } + + // Free the buffer containing the issuerInfo + free(pIssuerInfo); + } + + // Free the buffer containing the subjectInfo + free(pSubjectInfo); + } + + // Free necessary certificate information + if (certInfo.lpszSubjectInfo) LocalFree(certInfo.lpszSubjectInfo); + if (certInfo.lpszIssuerInfo) LocalFree(certInfo.lpszIssuerInfo); + if (certInfo.lpszProtocolName) LocalFree(certInfo.lpszProtocolName); + if (certInfo.lpszSignatureAlgName) LocalFree(certInfo.lpszSignatureAlgName); + if (certInfo.lpszEncryptionAlgName) LocalFree(certInfo.lpszEncryptionAlgName); + } + else + { + DbgTrace(0, "-InternalRpc- Unable to obtain server certificate struct, error = %0x\n", GetLastError()); + } + } + else + { + // Decided to no give the user a choice to accept invalid server certificate + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_SERVER_CERTIFICATE); + } + } + else + { + DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + + // Close the request handle + WinHttpCloseHandle(hRequest); + } + else + { + DbgTrace(0, "-InternalRpc- Unable to open http request, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } while (attemptRetry && retriesAllowed--); + + // Free the rpc target wide string buffer + free(pWideRpcTarget); + } + else + { + DbgTrace(0, "-InternalRpc- Error converting method name to wide string\n", 0); + } + + DbgTrace(1, "-InternalRpc- End, retStatus = %d\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +Rpc( + IN RpcSession *pSession, + IN char *pMethod, + IN long flags, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int retries = 0; + + DbgTrace(1, "-Rpc- Start\n", 0); + + // Retry the RPC as needed + do + { + // Issue the RPC + retStatus = InternalRpc(pSession, + pMethod, + flags, + pRequestData, + ppResponseData, + pResponseDataLen); + + // Account for this try + retries ++; + + } while (CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE + && retries < MAX_RPC_RETRIES); + + DbgTrace(1, "-Rpc- End, retStatus = %d\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +InitializeRpc(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + + DbgTrace(1, "-InitializeRpc- Start\n", 0); + + // Nothing to do for windows + + DbgTrace(1, "-InitializeRpc- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/AssemblyInfo.cs b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/AssemblyInfo.cs new file mode 100644 index 00000000..2548f91a --- /dev/null +++ b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/AssemblyInfo.cs @@ -0,0 +1,57 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("AuthToken Wrapper")] +[assembly: AssemblyDescription("C# Wrapper for Authentication Tokens")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Novell, Inc")] +[assembly: AssemblyProduct("CASA")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.7.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("../../AuthToken.snk")] +[assembly: AssemblyKeyName("")] diff --git a/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/AuthToken.snk b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/AuthToken.snk new file mode 100644 index 00000000..a319b439 Binary files /dev/null and b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/AuthToken.snk differ diff --git a/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/Authtoken.cs b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/Authtoken.cs new file mode 100644 index 00000000..1f23695c --- /dev/null +++ b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/Authtoken.cs @@ -0,0 +1,176 @@ +/*********************************************************************** + * + * 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: Jim Norman + * + ***********************************************************************/ + +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace Novell.Casa.Client.Auth +{ + /// + /// Summary description for Class1. + /// + public class Authtoken + { + private const string AUTH_LIBRARY = "C:\\Program Files\\Novell\\CASA\\lib\\authtoken"; + private const int BUFFER_OVERFLOW = 6; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct LUID + { + public int luidLow; + public int luidHigh; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public class SSCS_EXT_T + { + public int extID = 0; // defined to identify the extension + public int version = 0; // defined as the version of the specified extension + public IntPtr ext; // points to the actual extension + } ; + + [DllImport(AUTH_LIBRARY, CharSet=CharSet.None) ] + private static extern int ObtainAuthToken + ( + [In] byte[] baService, + [In] byte[] baHost, + [In, Out] byte[] baToken, + [In, Out] ref int iTokenLength + ); + + [DllImport(AUTH_LIBRARY, CharSet=CharSet.None) ] + private static extern int ObtainAuthTokenEx + ( + [In] byte[] baService, + [In] byte[] baHost, + [In, Out] byte[] baToken, + [In, Out] ref int iTokenLength, + [In] SSCS_EXT_T ext + ); + + + public Authtoken() + { + } + + + public static byte[] ObtainAuthToken(string sService, string sHost) + { + return ObtainAuthToken(sService, sHost, null); + } + + public static byte[] ObtainAuthToken(string sService, string sHost, WinLuid luid) + { + int rcode = 0; + byte[] baService = null; + byte[] baHost = null; + int bufferSize = 0; + bool bLuidPassedIn = false; + + byte[] baToken = new byte[bufferSize]; + + // convert service to ascii byte array + if (sService != null) + { + baService = Encoding.ASCII.GetBytes(sService); + } + else + { + throw new Exception("Invalid parameter"); + } + + // convert host to ascii byte array + if (sHost != null) + { + baHost = Encoding.ASCII.GetBytes(sHost); + } + else + { + throw new Exception("Invalid parameter"); + } + + + SSCS_EXT_T ext = new SSCS_EXT_T(); + if ((luid.GetHighPart() != 0) || (luid.GetLowPart() != 0)) + { + // allocate a structure to marshal + LUID sluid = new LUID(); + sluid.luidHigh = luid.GetHighPart(); + sluid.luidLow = luid.GetLowPart(); + + ext.extID = 1; + ext.version = 1; + ext.ext = Marshal.AllocHGlobal(Marshal.SizeOf(sluid)); + + Marshal.StructureToPtr(sluid, ext.ext, false); + bLuidPassedIn = true; + } + + + // call with buffersize of 0. This way we determine the exact size. + try + { + if (bLuidPassedIn) + { + rcode = ObtainAuthTokenEx(baService, baHost, baToken, ref bufferSize, ext); + } + else + { + rcode = ObtainAuthToken(baService, baHost, baToken, ref bufferSize); + } + + int test = (rcode & BUFFER_OVERFLOW); + if (test == BUFFER_OVERFLOW) + { + // now allocate the proper size + baToken = new byte[bufferSize]; + rcode = ObtainAuthToken(baService, baHost, baToken, ref bufferSize); + } + } + catch (Exception e) + { + LogMessage(e.ToString()); + return null; + } + + if (ext.ext != IntPtr.Zero) + Marshal.FreeHGlobal(ext.ext); + + if (rcode != 0) + { + throw new Exception(rcode.ToString()); + } + else + { + return baToken; + } + } + + private static void LogMessage(string sMessage) + { + System.Diagnostics.Trace.WriteLine("(C#)AuthToken: " + sMessage); + } + } +} diff --git a/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/Novell.Casa.Client.csproj b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/Novell.Casa.Client.csproj new file mode 100644 index 00000000..89da51ec --- /dev/null +++ b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/Novell.Casa.Client.csproj @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/WinLuid.cs b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/WinLuid.cs new file mode 100644 index 00000000..bb7e753d --- /dev/null +++ b/CASA-auth-token/client/csharp/Novell.Casa.Authtoken/WinLuid.cs @@ -0,0 +1,29 @@ +using System; + +namespace Novell.Casa.Client.Auth +{ + /// + /// Summary description for WinLuid. + /// + public class WinLuid + { + private int m_low = 0; + private int m_high = 0; + + public WinLuid(int lowPart, int highPart ) + { + m_low = lowPart; + m_high = highPart; + } + + public int GetLowPart() + { + return m_low; + } + + public int GetHighPart() + { + return m_high; + } + } +} diff --git a/CASA-auth-token/client/csharp/README b/CASA-auth-token/client/csharp/README new file mode 100644 index 00000000..2fb1d8e2 --- /dev/null +++ b/CASA-auth-token/client/csharp/README @@ -0,0 +1,68 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ +/*********************************************************************** + * + * README for Novell.Casa.Client.Auth CSHARP Library + * + ***********************************************************************/ + +INTRODUCTION + +Novell.Casa.Client.Auth CSHARP Library provides a class for CSHARP client +applications to obtain authentication tokens from the CASA Authentication +Token Infrastructure. + +CLIENT APPLICATION PROGRAMMING NOTES + +The Novell.Casa.Client.Auth.Authtoken class provides static method ObtainAuthToken() +to allow client applications to obtain CASA Authentication Tokens. The caller must +supply the name of the service to which it wants to authenticate along with the name +of the host where it resides to the static method. The returned authentication token +is a Base64 encoded string. + +Applications utilizing CASA Authentication Tokens as passwords in protocols that require the +transfer of user name and password credentials should verify or remove any password length limits +as the length of CASA Authentication Tokens may be over 1K bytes. The size of the CASA Authentication +Tokens is directly dependent on the amount of identity information configured as required by the +consuming service. These applications should also set the user name to "CasaPrincipal". + +For examples of code which uses the Novell.Casa.Client.Auth.Authtoken class look at the test +application under the test folder. + +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/client/csharp/TODO b/CASA-auth-token/client/csharp/TODO new file mode 100644 index 00000000..41061da2 --- /dev/null +++ b/CASA-auth-token/client/csharp/TODO @@ -0,0 +1,15 @@ +/*********************************************************************** + * + * TODO for Novell.Casa.Client.Auth CSHARP Library + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for the +Novell.Casa.Client.Auth CSHARP library. + +OUTSTANDING ITEMS + +- Include it in the Linux Client build/rpm. + diff --git a/CASA-auth-token/client/csharp/test/App.ico b/CASA-auth-token/client/csharp/test/App.ico new file mode 100644 index 00000000..3a5525fd Binary files /dev/null and b/CASA-auth-token/client/csharp/test/App.ico differ diff --git a/CASA-auth-token/client/csharp/test/AssemblyInfo.cs b/CASA-auth-token/client/csharp/test/AssemblyInfo.cs new file mode 100644 index 00000000..177a4f0e --- /dev/null +++ b/CASA-auth-token/client/csharp/test/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/CASA-auth-token/client/csharp/test/Class1.cs b/CASA-auth-token/client/csharp/test/Class1.cs new file mode 100644 index 00000000..313e455b --- /dev/null +++ b/CASA-auth-token/client/csharp/test/Class1.cs @@ -0,0 +1,74 @@ +/*********************************************************************** + * + * 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: Jim Norman + * + ***********************************************************************/ + +using System; +using Novell.Casa.Client.Auth; + +namespace TestClientAuth +{ + /// + /// Summary description for Class1. + /// + class Class1 + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main(string[] args) + { + if (args.Length < 1) + { + Console.WriteLine("Usage: TestClientAuth [server]"); + Console.WriteLine("Press enter to continue"); + Console.ReadLine(); + return; + } + + try + { + + WinLuid luid = new WinLuid(1234, 5678); + Authtoken.ObtainAuthToken("testService", args[0], luid); + + byte[] baToken = Authtoken.ObtainAuthToken("testService", args[0]); + Console.WriteLine("Token returned: ("+ baToken.Length + ")"); + for (int i=0; i + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/client/include/Makefile.am b/CASA-auth-token/client/include/Makefile.am new file mode 100644 index 00000000..f506f2fe --- /dev/null +++ b/CASA-auth-token/client/include/Makefile.am @@ -0,0 +1,40 @@ +####################################################################### +# +# 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 = + +CFILES = + +EXTRA_DIST = *.h + +.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/client/include/casa_c_authtoken.h b/CASA-auth-token/client/include/casa_c_authtoken.h new file mode 100644 index 00000000..4dd91ad3 --- /dev/null +++ b/CASA-auth-token/client/include/casa_c_authtoken.h @@ -0,0 +1,102 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _CASA_C_AUTHTOKEN_H_ +#define _CASA_C_AUTHTOKEN_H_ + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" +{ +#endif + +//===[ Include files ]===================================================== + +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef SSCS_CALL +#if defined(WIN32) +#define SSCS_CALL __stdcall +#else +#define SSCS_CALL +#endif +#endif + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +extern CasaStatus SSCS_CALL +ObtainAuthToken( + IN const char *pServiceName, + IN const char *pHostName, + INOUT char *pAuthTokenBuf, + INOUT int *pAuthTokenBufLen); +// +// Arguments: +// pServiceName - +// Pointer to NULL terminated string that contains the +// name of the service to which the client is trying to +// authenticate. +// +// pHostName - +// Pointer to NULL terminated string that contains the +// name of the host where resides the service to which the +// client is trying to authenticate. Note that the name +// can either be a DNS name or a dotted IP address. +// +// pAuthTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pAuthTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pAuthTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pAuthTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pAuthTokenBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified +// service at host. +//=======================================================================-- + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif // #if defined(__cplusplus) || defined(c_plusplus) + +#endif // #ifndef _CASA_C_AUTHTOKEN_H_ + diff --git a/CASA-auth-token/client/include/list_entry.h b/CASA-auth-token/client/include/list_entry.h new file mode 100644 index 00000000..f482b464 --- /dev/null +++ b/CASA-auth-token/client/include/list_entry.h @@ -0,0 +1,187 @@ +/*********************************************************************** + * + * Copyright (C) 2005-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. + * + ***********************************************************************/ + +#ifndef _LIST_ENTRY_H_ +#define _LIST_ENTRY_H_ + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" +{ +#endif + +//===[ Include files ]===================================================== + +//#include + +//===[ Type definitions ]================================================== + +#ifndef CSAPI +#if defined(WIN32) +#define CSAPI __stdcall +#else +#define CSAPI +#endif +#endif + +#ifndef IN +#define IN +#endif + +#ifndef OUT +#define OUT +#endif + +#ifndef INOUT +#define INOUT +#endif + +#ifndef WIN32 +// +// LIST_ENTRY Type +// Doubly linked list structure +// +typedef struct _LIST_ENTRY +{ + struct _LIST_ENTRY * volatile Flink; + struct _LIST_ENTRY * volatile Blink; +} LIST_ENTRY, *PLIST_ENTRY; +#endif + +//===[ Inlines functions ]=============================================== + +// +// Inline functions for operating on LIST_ENTRY double-linked lists +// + +__inline static void InitializeListHead( + IN PLIST_ENTRY pListEntry ) +{ + pListEntry->Flink = pListEntry->Blink = pListEntry; +} + +__inline static void InsertEntryAfter( + IN PLIST_ENTRY pListEntry, + IN PLIST_ENTRY pAfterEntry ) +{ + pListEntry->Flink = pAfterEntry->Flink; + pListEntry->Blink = pAfterEntry; + pListEntry->Flink->Blink = pAfterEntry->Flink = pListEntry; +} + +__inline static void InsertEntryBefore( + IN PLIST_ENTRY pListEntry, + IN PLIST_ENTRY pBeforeEntry ) +{ + pListEntry->Flink = pBeforeEntry; + pListEntry->Blink = pBeforeEntry->Blink; + pListEntry->Blink->Flink = pBeforeEntry->Blink = pListEntry; +} + +__inline static void InsertHeadList( + IN PLIST_ENTRY pListHead, + IN PLIST_ENTRY pListEntry ) +{ + pListEntry->Blink = pListHead; + pListEntry->Flink = pListHead->Flink; + pListEntry->Flink->Blink = pListHead->Flink = pListEntry; +} + +__inline static void InsertTailList( + IN PLIST_ENTRY pListHead, + IN PLIST_ENTRY pListEntry ) +{ + pListEntry->Flink = pListHead; + pListEntry->Blink = pListHead->Blink; + pListEntry->Blink->Flink = pListHead->Blink = pListEntry; +} + +__inline static bool IsListEmpty( + IN PLIST_ENTRY pListHead ) +{ + bool rc = false; + if(pListHead->Flink == pListHead) + rc = true; + return(rc); +} + +__inline static void RemoveEntryList( + IN PLIST_ENTRY pListEntry ) +{ + pListEntry->Flink->Blink = pListEntry->Blink; + pListEntry->Blink->Flink = pListEntry->Flink; + pListEntry->Flink = pListEntry->Blink = (PLIST_ENTRY) 0xbaadf00d; +} + +__inline static PLIST_ENTRY RemoveHeadList( + IN PLIST_ENTRY pListHead ) +{ + PLIST_ENTRY Entry = (PLIST_ENTRY)0; + if(pListHead->Flink != pListHead) + { + Entry = pListHead->Flink; + RemoveEntryList(Entry); + } + return(Entry); +} + +__inline static PLIST_ENTRY RemoveTailList( + IN PLIST_ENTRY pListHead ) +{ + PLIST_ENTRY Entry= (PLIST_ENTRY)0; + if(pListHead->Blink != pListHead) + { + Entry = pListHead->Blink; + RemoveEntryList(Entry); + } + return(Entry); +} + +__inline static PLIST_ENTRY GetFirstListEntry( + IN PLIST_ENTRY pList) +{ + PLIST_ENTRY Entry = (PLIST_ENTRY)0; + if(pList != pList->Flink) + Entry = pList->Flink; + return(Entry); +} + +__inline static PLIST_ENTRY GetNextListEntry( + IN PLIST_ENTRY pList, + IN PLIST_ENTRY pEntry) +{ + PLIST_ENTRY Entry = (PLIST_ENTRY)0; + if(pList != pEntry->Flink) + Entry = pEntry->Flink; + return(Entry); +} + + +//========================================================================= + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif // #if defined(__cplusplus) || defined(c_plusplus) + +#endif // #ifndef _LIST_ENTRY_H_ + + diff --git a/CASA-auth-token/client/include/proto.h b/CASA-auth-token/client/include/proto.h new file mode 100644 index 00000000..87b90eb1 --- /dev/null +++ b/CASA-auth-token/client/include/proto.h @@ -0,0 +1,70 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _PROTO_H_ +#define _PROTO_H_ + +//===[ Include files ]===================================================== + + +//===[ Type definitions ]================================================== + +// +// XML Constants for the documents exchanged between the CASA Client +// and the CASA Server. +// +#define XML_DECLARATION "" +#define AUTH_REQUEST_ELEMENT_NAME "auth_req" +#define AUTH_RESPONSE_ELEMENT_NAME "auth_resp" +#define GET_AUTH_POLICY_REQUEST_ELEMENT_NAME "get_auth_policy_req" +#define GET_AUTH_POLICY_RESPONSE_ELEMENT_NAME "get_auth_policy_resp" +#define GET_AUTH_TOKEN_REQUEST_ELEMENT_NAME "get_auth_tok_req" +#define GET_AUTH_TOKEN_RESPONSE_ELEMENT_NAME "get_auth_tok_resp" +#define AUTH_MECH_TOKEN_ELEMENT_NAME "auth_mech_token" +#define AUTH_TOKEN_ELEMENT_NAME "auth_token" +#define AUTH_POLICY_ELEMENT_NAME "auth_policy" +#define AUTH_SOURCE_ELEMENT_NAME "auth_source" +#define STATUS_ELEMENT_NAME "status" +#define SESSION_TOKEN_ELEMENT_NAME "session_token" +#define LIFETIME_ELEMENT_NAME "lifetime" +#define DESCRIPTION_ELEMENT_NAME "description" +#define SERVICE_ELEMENT_NAME "service" +#define HOST_ELEMENT_NAME "host" +#define REALM_ELEMENT_NAME "realm" +#define MECHANISM_ELEMENT_NAME "mechanism" +#define MECHANISM_INFO_ELEMENT_NAME "mechanism_info" +#define SIGNATURE_ELEMENT_NAME "signature" +#define TYPE_ELEMENT_NAME "type" +#define IDENTITY_TOKEN_ELEMENT_NAME "ident_token" + +// +// HTTP Status Codes +// +#define HTTP_OK_STATUS_CODE "200" +#define HTTP_UNAUTHORIZED_STATUS_CODE "401" +#define HTTP_NOT_FOUND_STATUS_CODE "404" +#define HTTP_SERVER_ERROR_STATUS_CODE "500" + + +#endif // _PROTO_H_ diff --git a/CASA-auth-token/client/include/windows/casa_c_authtoken_ex.h b/CASA-auth-token/client/include/windows/casa_c_authtoken_ex.h new file mode 100644 index 00000000..76960715 --- /dev/null +++ b/CASA-auth-token/client/include/windows/casa_c_authtoken_ex.h @@ -0,0 +1,109 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _CASA_C_AUTHTOKEN_EX_H_ +#define _CASA_C_AUTHTOKEN_EX_H_ + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" +{ +#endif + +//===[ Include files ]===================================================== + +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef SSCS_CALL +#if defined(WIN32) +#define SSCS_CALL __stdcall +#else +#define SSCS_CALL +#endif +#endif + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +CasaStatus SSCS_CALL +ObtainAuthTokenEx( + IN const char *pServiceName, + IN const char *pHostName, + INOUT char *pAuthTokenBuf, + INOUT int *pAuthTokenBufLen, + IN void *pCredStoreScope); +// +// Arguments: +// pServiceName - +// Pointer to NULL terminated string that contains the +// name of the service to which the client is trying to +// authenticate. +// +// pHostName - +// Pointer to NULL terminated string that contains the +// name of the host where resides the service to which the +// client is trying to authenticate. Note that the name +// can either be a DNS name or a dotted IP address. +// +// pAuthTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pAuthTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pAuthTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pAuthTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pAuthTokenBuf is +// not large enough. +// +// pCredStoreScope - +// Pointer to CASA structure for scoping credential store access +// to specific users. This can only be leveraged by applications +// running in the context of System. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified +// service at host. The user is scoped using the info associated +// with the magic cookie. +//=======================================================================-- + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif // #if defined(__cplusplus) || defined(c_plusplus) + +#endif // #ifndef _CASA_C_AUTHTOKEN_EX_H_ + diff --git a/CASA-auth-token/client/package/Makefile.am b/CASA-auth-token/client/package/Makefile.am new file mode 100644 index 00000000..4c1b4130 --- /dev/null +++ b/CASA-auth-token/client/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 = $(TARGET_OS) + +DIST_SUBDIRS = linux windows + +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/client/package/linux/CASA_auth_token_client.changes b/CASA-auth-token/client/package/linux/CASA_auth_token_client.changes new file mode 100644 index 00000000..8629e98d --- /dev/null +++ b/CASA-auth-token/client/package/linux/CASA_auth_token_client.changes @@ -0,0 +1,83 @@ +------------------------------------------------------------------- +Thu Nov 9 17:16:36 MST 2006 - jluciani@novell.com + +- Finished the changes to enable client/ATS communications + over SSL. + +------------------------------------------------------------------- +Tue Nov 7 16:01:11 MST 2006 - jluciani@novell.com + +- Made changes to enable client/ats communication over SSL. (Not quite + done with this yet). + +- Updated the make system to allow Windows builds to be made from + the command line using Cygwin. + +------------------------------------------------------------------- +Thu Oct 19 09:20:24 MDT 2006 - jluciani@novell.com + +- Created client-devel RPM. + +- Made changes to conform to updates made to the Java components + with regard to the layout of files. + +------------------------------------------------------------------- +Tue Oct 10 08:46:22 MDT 2006 - jluciani@novell.com + +- Brought up to date the README and TODO files. + +------------------------------------------------------------------- +Mon Oct 9 09:28:37 MDT 2006 - jluciani@novell.com + +- Cleaned up compiler warnings that were present in some of the + components. + +------------------------------------------------------------------- +Fri Oct 6 14:22:54 MDT 2006 - schoi@novell.com + +- Add the CASA build check as dependency in spec file + +------------------------------------------------------------------- +Thu Oct 5 15:21:39 MDT 2006 - jluciani@novell.com + +- Ported the client to Linux and created the CASA_auth_token_client package. + +------------------------------------------------------------------- +Mon Oct 2 11:47:16 MDT 2006 - jluciani@novell.com + +- Made spec file modifications suggested by SuSE. The changes entailed + leveraging RPM macros instead of using my own scripts to make the + RPM more solid. + +------------------------------------------------------------------- +Thu Sep 14 17:41:40 MDT 2006 - jluciani@novell.com + +- Added rc script for Validate AuthToken Service. + +------------------------------------------------------------------- +Thu Sep 14 09:48:54 MDT 2006 - jluciani@novell.com + +- Created the Validate AuthToken Service and made all of the necessary changes + to allow it to be consumed by the AuthTokenValidate library. + +- Also made necessary spec file changes to support our configuration. + +------------------------------------------------------------------- +Tue Sep 5 08:37:35 MDT 2006 - jluciani@novell.com + +- Created client/server IPC libraries that will be utilized by libcasa_s_authtoken + to communicate with the Java Validate AuthToken Service (yet to be created) over + DOMAIN sockets. The service will utilize the libraries via JNI to be able to + process requests sent using DOMAIN sockets. + +------------------------------------------------------------------- +Tue Aug 15 10:09:32 MDT 2006 - schoi@novell.com +- Fixed CASA_auth_token_devel build requirement for CASA_auth_token_svc + +------------------------------------------------------------------- +Mon Aug 7 10:28:32 MDT 2006 - schoi@novell.com +- This file has been created for CASA_auth_token_native project for the first + time. + +------------------------------------------------------------------- + diff --git a/CASA-auth-token/client/package/linux/CASA_auth_token_native.changes b/CASA-auth-token/client/package/linux/CASA_auth_token_native.changes new file mode 100644 index 00000000..8629e98d --- /dev/null +++ b/CASA-auth-token/client/package/linux/CASA_auth_token_native.changes @@ -0,0 +1,83 @@ +------------------------------------------------------------------- +Thu Nov 9 17:16:36 MST 2006 - jluciani@novell.com + +- Finished the changes to enable client/ATS communications + over SSL. + +------------------------------------------------------------------- +Tue Nov 7 16:01:11 MST 2006 - jluciani@novell.com + +- Made changes to enable client/ats communication over SSL. (Not quite + done with this yet). + +- Updated the make system to allow Windows builds to be made from + the command line using Cygwin. + +------------------------------------------------------------------- +Thu Oct 19 09:20:24 MDT 2006 - jluciani@novell.com + +- Created client-devel RPM. + +- Made changes to conform to updates made to the Java components + with regard to the layout of files. + +------------------------------------------------------------------- +Tue Oct 10 08:46:22 MDT 2006 - jluciani@novell.com + +- Brought up to date the README and TODO files. + +------------------------------------------------------------------- +Mon Oct 9 09:28:37 MDT 2006 - jluciani@novell.com + +- Cleaned up compiler warnings that were present in some of the + components. + +------------------------------------------------------------------- +Fri Oct 6 14:22:54 MDT 2006 - schoi@novell.com + +- Add the CASA build check as dependency in spec file + +------------------------------------------------------------------- +Thu Oct 5 15:21:39 MDT 2006 - jluciani@novell.com + +- Ported the client to Linux and created the CASA_auth_token_client package. + +------------------------------------------------------------------- +Mon Oct 2 11:47:16 MDT 2006 - jluciani@novell.com + +- Made spec file modifications suggested by SuSE. The changes entailed + leveraging RPM macros instead of using my own scripts to make the + RPM more solid. + +------------------------------------------------------------------- +Thu Sep 14 17:41:40 MDT 2006 - jluciani@novell.com + +- Added rc script for Validate AuthToken Service. + +------------------------------------------------------------------- +Thu Sep 14 09:48:54 MDT 2006 - jluciani@novell.com + +- Created the Validate AuthToken Service and made all of the necessary changes + to allow it to be consumed by the AuthTokenValidate library. + +- Also made necessary spec file changes to support our configuration. + +------------------------------------------------------------------- +Tue Sep 5 08:37:35 MDT 2006 - jluciani@novell.com + +- Created client/server IPC libraries that will be utilized by libcasa_s_authtoken + to communicate with the Java Validate AuthToken Service (yet to be created) over + DOMAIN sockets. The service will utilize the libraries via JNI to be able to + process requests sent using DOMAIN sockets. + +------------------------------------------------------------------- +Tue Aug 15 10:09:32 MDT 2006 - schoi@novell.com +- Fixed CASA_auth_token_devel build requirement for CASA_auth_token_svc + +------------------------------------------------------------------- +Mon Aug 7 10:28:32 MDT 2006 - schoi@novell.com +- This file has been created for CASA_auth_token_native project for the first + time. + +------------------------------------------------------------------- + diff --git a/CASA-auth-token/client/package/linux/Makefile.am b/CASA-auth-token/client/package/linux/Makefile.am new file mode 100644 index 00000000..1cace376 --- /dev/null +++ b/CASA-auth-token/client/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_native.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/client/package/windows/Makefile.am b/CASA-auth-token/client/package/windows/Makefile.am new file mode 100644 index 00000000..7cbf38f2 --- /dev/null +++ b/CASA-auth-token/client/package/windows/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: Greg Richardson +# +####################################################################### + +SUBDIRS = authtokenclient_msm authtokenclient_msi + +DIST_SUBDIRS = authtokenclient_msm authtokenclient_msi + +EXTRA_DIST = + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C authtokenclient_msm $@ + $(MAKE) -C authtokenclient_msi $@ + +clean-local: + if [ -d lib ]; then rm -rf lib; fi + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/client/package/windows/authtokenclient_msi/Makefile.am b/CASA-auth-token/client/package/windows/authtokenclient_msi/Makefile.am new file mode 100644 index 00000000..c97ba445 --- /dev/null +++ b/CASA-auth-token/client/package/windows/authtokenclient_msi/Makefile.am @@ -0,0 +1,69 @@ +####################################################################### +# +# Copyright (C) 2004 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: Greg Richardson +# +####################################################################### + +SUBDIRS = + +DIST_SUBDIRS = + +EXTRA_DIST = authtokenclient_msi.vdproj + +if DEBUG +TARGET_CFG = Debug +else +TARGET_CFG = Release +endif + +PACKAGE = authtokenclient_msi +TARGET_FILE = $(PACKAGE).msi +LOG_FILE = $(PACKAGE).log + +.PHONY: package package-clean package-install package-uninstall devenv + +package: $(TARGET_FILE) + +devenv: + @if ! test -x "$(VSINSTALLDIR)/devenv.exe"; then echo "Error: Microsoft Visual Studio .NET is currently required to build MSI and MSM packages"; exit 1; fi + +$(TARGET_FILE): devenv + @rm -f $(LOG_FILE) $@ + @CMD='"$(VSINSTALLDIR)/devenv.exe" ../../../auth.sln /build $(TARGET_CFG) /project $(PACKAGE) /out $(LOG_FILE)'; \ + echo $$CMD; \ + if eval $$CMD; then \ + ls -l $(TARGET_CFG)/$(TARGET_FILE); \ + else \ + grep -a "ERROR:" $(LOG_FILE); \ + fi + +package-clean clean-local: + rm -rf Release/* Release Debug/* Debug*/Release */Debug *.log *.suo + +clean: + rm -rf Release/* Release Debug/* Debug */Release */Debug *.log *.suo + +distclean-local: package-clean + rm -f Makefile + +maintainer-clean-local: + rm -f Makefile.in + + + diff --git a/CASA-auth-token/client/package/windows/authtokenclient_msi/authtokenclient_msi.vdproj b/CASA-auth-token/client/package/windows/authtokenclient_msi/authtokenclient_msi.vdproj new file mode 100644 index 00000000..9fc83ed1 --- /dev/null +++ b/CASA-auth-token/client/package/windows/authtokenclient_msi/authtokenclient_msi.vdproj @@ -0,0 +1,699 @@ +"DeployProject" +{ +"VSVersion" = "3:701" +"ProjectType" = "8:{2C2AF0D9-9B47-4FE5-BEF2-169778172667}" +"IsWebType" = "8:FALSE" +"ProjectName" = "8:authtokenclient_msi" +"LanguageId" = "3:1033" +"CodePage" = "3:1252" +"UILanguageId" = "3:1033" +"SccProjectName" = "8:" +"SccLocalPath" = "8:" +"SccAuxPath" = "8:" +"SccProvider" = "8:" + "Hierarchy" + { + "Entry" + { + "MsmKey" = "8:_161A15C5C78C4BBD8AEDF896DCFEDE6B" + "OwnerKey" = "8:_634B25C086554FB78146A1549281714E" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_634B25C086554FB78146A1549281714E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + } + "Configurations" + { + "Debug" + { + "DisplayName" = "8:Debug" + "IsDebugOnly" = "11:TRUE" + "IsReleaseOnly" = "11:FALSE" + "OutputFilename" = "8:Debug\\authtokenclient_msi.msi" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:2" + } + "Release" + { + "DisplayName" = "8:Release" + "IsDebugOnly" = "11:FALSE" + "IsReleaseOnly" = "11:TRUE" + "OutputFilename" = "8:Release\\authtokenclient_msi.msi" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:2" + } + } + "Deployable" + { + "CustomAction" + { + } + "DefaultFeature" + { + "Name" = "8:DefaultFeature" + "Title" = "8:" + "Description" = "8:" + } + "ExternalPersistence" + { + "LaunchCondition" + { + "{2522A265-4974-4402-83C5-3B575A2E935A}:_17958A6305A24EF4880B1337DA4FFD51" + { + "Name" = "8:.NET Framework" + "Message" = "8:[VSDNETMSG]" + "SupportedRuntimes" = "8:1.1.4322;2.0.50727" + "InstallUrl" = "8:http://go.microsoft.com/fwlink/?LinkId=9832" + } + } + } + "Feature" + { + } + "File" + { + } + "FileType" + { + } + "Folder" + { + "{78BAF5CE-F2E5-45BE-83BC-DB6AF387E941}:_5822614DE62647039F8AF6B0781851A7" + { + "Name" = "8:#1916" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:DesktopFolder" + "Folders" + { + } + } + "{58C0ADA3-3CEA-43BD-A3B3-2EA121BC8217}:_BADBE39F262C4F79B42417C62DF02E55" + { + "DefaultLocation" = "8:[ProgramFilesFolder][Manufacturer]\\[ProductName]" + "Name" = "8:#1925" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:TARGETDIR" + "Folders" + { + } + } + "{78BAF5CE-F2E5-45BE-83BC-DB6AF387E941}:_CA7A8DC7331A4C47A8C7CDE8C53FE9FA" + { + "Name" = "8:#1919" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:ProgramMenuFolder" + "Folders" + { + } + } + } + "LaunchCondition" + { + } + "Locator" + { + } + "MsiBootstrapper" + { + "LangId" = "3:1033" + } + "Product" + { + "Name" = "8:Microsoft Visual Studio" + "ProductName" = "8:authtokenclient" + "ProductCode" = "8:{6D3AAA36-871A-4427-9311-FC3FE2F17511}" + "PackageCode" = "8:{4F7846D3-7607-463B-8BA7-A76832D29411}" + "UpgradeCode" = "8:{69C5F129-788A-4487-9397-331C0A313A2D}" + "RestartWWWService" = "11:FALSE" + "RemovePreviousVersions" = "11:FALSE" + "DetectNewerInstalledVersion" = "11:TRUE" + "ProductVersion" = "8:1.0.0" + "Manufacturer" = "8:Novell" + "ARPHELPTELEPHONE" = "8:" + "ARPHELPLINK" = "8:" + "Title" = "8:authtokenclient" + "Subject" = "8:" + "ARPCONTACT" = "8:Novell" + "Keywords" = "8:" + "ARPCOMMENTS" = "8:" + "ARPURLINFOABOUT" = "8:" + "ARPPRODUCTICON" = "8:" + "ARPIconIndex" = "3:0" + "SearchPath" = "8:" + "UseSystemSearchPath" = "11:TRUE" + } + "Registry" + { + "HKLM" + { + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_3C4408A91276415C99DB57B858A91555" + { + "Name" = "8:Software" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_22714EABC4F3412BB3230B8EA95CFB08" + { + "Name" = "8:[Manufacturer]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + } + "Values" + { + } + } + } + "Values" + { + } + } + } + } + "HKCU" + { + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_93C508CBDBB34C95B9C890F165C081F1" + { + "Name" = "8:Software" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{6A471EEF-D31B-40F8-BCF6-C9E8EC783F36}:_B7A9FC8108DB4E249F31D12A434C1844" + { + "Name" = "8:[Manufacturer]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + } + "Values" + { + } + } + } + "Values" + { + } + } + } + } + "HKCR" + { + "Keys" + { + } + } + "HKU" + { + "Keys" + { + } + } + "HKPU" + { + "Keys" + { + } + } + } + "Sequences" + { + } + "Shortcut" + { + } + "UserInterface" + { + "{B654A020-6903-4E6A-A86C-75DC463DB54B}:_1240F250BDDA45B084738491D53CCA13" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdUserInterface.wim" + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_2873941BB49A4737AF72ED5E788318F7" + { + "Name" = "8:#1902" + "Sequence" = "3:1" + "Attributes" = "3:3" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_10695426506044F6B667E02B3E33A00E" + { + "Sequence" = "3:100" + "DisplayName" = "8:Finished" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdFinishedDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "UpdateText" + { + "Name" = "8:UpdateText" + "DisplayName" = "8:#1058" + "Description" = "8:#1158" + "Type" = "3:15" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1258" + "DefaultValue" = "8:#1258" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_353966B93CCA47F89005110A192B33E0" + { + "Name" = "8:#1900" + "Sequence" = "3:2" + "Attributes" = "3:1" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_A41DEF6D91134F42BA300A817856F7C2" + { + "Sequence" = "3:300" + "DisplayName" = "8:Confirm Installation" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminConfirmDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_D915672F6CE04B29A5482A7E9297CE42" + { + "Sequence" = "3:100" + "DisplayName" = "8:Welcome" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminWelcomeDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "CopyrightWarning" + { + "Name" = "8:CopyrightWarning" + "DisplayName" = "8:#1002" + "Description" = "8:#1102" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1202" + "DefaultValue" = "8:#1202" + "UsePlugInResources" = "11:TRUE" + } + "Welcome" + { + "Name" = "8:Welcome" + "DisplayName" = "8:#1003" + "Description" = "8:#1103" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1203" + "DefaultValue" = "8:#1203" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_E8BB0C75759A4ECA9292D5EB62A4B1DD" + { + "Sequence" = "3:200" + "DisplayName" = "8:Installation Folder" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminFolderDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_72EFC743AB3B42B6994F5EC55E41631F" + { + "Name" = "8:#1901" + "Sequence" = "3:1" + "Attributes" = "3:2" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_9D455462808342AE837694F103194C3E" + { + "Sequence" = "3:100" + "DisplayName" = "8:Progress" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdProgressDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "ShowProgress" + { + "Name" = "8:ShowProgress" + "DisplayName" = "8:#1009" + "Description" = "8:#1109" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{B654A020-6903-4E6A-A86C-75DC463DB54B}:_A0A8360C0E0D46ACB472E47806B666D5" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdBasicDialogs.wim" + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_D708D6BFB2C946BB9BCCC9F6F2CAE0FA" + { + "Name" = "8:#1902" + "Sequence" = "3:2" + "Attributes" = "3:3" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_964E18CF17534E789061E20F26EE5EDA" + { + "Sequence" = "3:100" + "DisplayName" = "8:Finished" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminFinishedDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_E294259CC9424A6EB901523FCAD0D0CC" + { + "Name" = "8:#1900" + "Sequence" = "3:1" + "Attributes" = "3:1" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_E227037047AF41C394E3138699F6DD62" + { + "Sequence" = "3:300" + "DisplayName" = "8:Confirm Installation" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdConfirmDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_EF6CBFADEBBA4F4BA427709FD0C72385" + { + "Sequence" = "3:100" + "DisplayName" = "8:Welcome" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdWelcomeDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "CopyrightWarning" + { + "Name" = "8:CopyrightWarning" + "DisplayName" = "8:#1002" + "Description" = "8:#1102" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1202" + "DefaultValue" = "8:#1202" + "UsePlugInResources" = "11:TRUE" + } + "Welcome" + { + "Name" = "8:Welcome" + "DisplayName" = "8:#1003" + "Description" = "8:#1103" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1203" + "DefaultValue" = "8:#1203" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{8D9DEE8B-DD8B-4F48-9072-C4364E4F4011}:_FC54039B5B444B8C8D7C64B693C25B14" + { + "Name" = "8:#1901" + "Sequence" = "3:2" + "Attributes" = "3:2" + "Dialogs" + { + "{18ADD6EC-89FE-4ED7-AD3E-211C40278470}:_E79C486A92E54E4881FBD841C4649B83" + { + "Sequence" = "3:100" + "DisplayName" = "8:Progress" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminProgressDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "ShowProgress" + { + "Name" = "8:ShowProgress" + "DisplayName" = "8:#1009" + "Description" = "8:#1109" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + } + "MergeModule" + { + "{35A69C6E-5BA4-440D-803D-762B59A45393}:_161A15C5C78C4BBD8AEDF896DCFEDE6B" + { + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:TRUE" + "SourcePath" = "8:dotnetfxredist_x86.msm" + "Properties" + { + } + "LanguageId" = "3:1033" + "Exclude" = "11:TRUE" + "Folder" = "8:" + "Feature" = "8:" + "IsolateTo" = "8:" + } + } + "ProjectOutput" + { + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_634B25C086554FB78146A1549281714E" + { + "SourcePath" = "8:..\\authtokenclient_msm\\Debug\\authtokenclient_msm.msm" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_BADBE39F262C4F79B42417C62DF02E55" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{C8405908-5026-4E77-B02F-9259856A17E8}" + "ShowKeyOutput" = "11:TRUE" + "ExcludeFilters" + { + } + "KeyOutputModule" + { + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:..\\authtokenclient_msm\\Debug\\authtokenclient_msm.msm" + "Properties" + { + "_F5F5F604B81645F8B6463F7A7D6A53AD.375AEECA1C3A4EC3AF37E3E5BE6711DD" + { + "Name" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD.375AEECA1C3A4EC3AF37E3E5BE6711DD" + "DisplayName" = "8:Module Retargetable Folder" + "Description" = "8:" + "Type" = "3:32769" + "ContextData" = "8:_RetargetableFolder" + "Attributes" = "3:6" + "Setting" = "3:1" + "UsePlugInResources" = "11:FALSE" + } + } + "LanguageId" = "3:1033" + "Exclude" = "11:FALSE" + "Folder" = "8:_BADBE39F262C4F79B42417C62DF02E55" + "Feature" = "8:" + "IsolateTo" = "8:" + } + } + } + "VJSharpPlugin" + { + } + } +} diff --git a/CASA-auth-token/client/package/windows/authtokenclient_msm/Makefile.am b/CASA-auth-token/client/package/windows/authtokenclient_msm/Makefile.am new file mode 100644 index 00000000..a3982068 --- /dev/null +++ b/CASA-auth-token/client/package/windows/authtokenclient_msm/Makefile.am @@ -0,0 +1,69 @@ +####################################################################### +# +# Copyright (C) 2004 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: Greg Richardson +# +####################################################################### + +SUBDIRS = + +DIST_SUBDIRS = + +EXTRA_DIST = authtokenclient_msm.vdproj + +if DEBUG +TARGET_CFG = Debug +else +TARGET_CFG = Release +endif + +PACKAGE = authtokenclient_msm +TARGET_FILE = $(PACKAGE).msm +LOG_FILE = $(PACKAGE).log + +.PHONY: package package-clean package-install package-uninstall devenv + +package: $(TARGET_FILE) + +devenv: + @if ! test -x "$(VSINSTALLDIR)/devenv.exe"; then echo "Error: Microsoft Visual Studio .NET is currently required to build MSI and MSM packages"; exit 1; fi + +$(TARGET_FILE): devenv + @rm -f $(LOG_FILE) $@ + @CMD='"$(VSINSTALLDIR)/devenv.exe" ../../../auth.sln /build $(TARGET_CFG) /project $(PACKAGE) /out $(LOG_FILE)'; \ + echo $$CMD; \ + if eval $$CMD; then \ + ls -l $(TARGET_CFG)/$(TARGET_FILE); \ + else \ + grep -a "ERROR:" $(LOG_FILE); \ + fi + +package-clean clean-local: + rm -rf Release/* Release Debug/* Debug*/Release */Debug *.log *.suo + +clean: + rm -rf Release/* Release Debug/* Debug */Release */Debug *.log *.suo + +distclean-local: package-clean + rm -f Makefile + +maintainer-clean-local: + rm -f Makefile.in + + + diff --git a/CASA-auth-token/client/package/windows/authtokenclient_msm/authtokenclient_msm.vdproj b/CASA-auth-token/client/package/windows/authtokenclient_msm/authtokenclient_msm.vdproj new file mode 100644 index 00000000..6c292476 --- /dev/null +++ b/CASA-auth-token/client/package/windows/authtokenclient_msm/authtokenclient_msm.vdproj @@ -0,0 +1,647 @@ +"DeployProject" +{ +"VSVersion" = "3:701" +"ProjectType" = "8:{DD7A5B58-C2F9-40FF-B2EF-0773356FB978}" +"IsWebType" = "8:FALSE" +"ProjectName" = "8:authtokenclient_msm" +"LanguageId" = "3:1033" +"CodePage" = "3:1252" +"UILanguageId" = "3:1033" +"SccProjectName" = "8:" +"SccLocalPath" = "8:" +"SccAuxPath" = "8:" +"SccProvider" = "8:" + "Hierarchy" + { + "Entry" + { + "MsmKey" = "8:_191525A919DD46AD8D70B7735EE4F451" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_22FDEF26EDCE4831A621BB20C7EB4508" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_313DE095D13281AF91A64E3F3D472413" + "OwnerKey" = "8:_7A5EA42289F94648877FA695EB1853CE" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3986DA1502244FFBB04A66472E74633B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_472FEAD17E7B45FF92E93D80B3379C47" + "OwnerKey" = "8:_8292EFFD84EF46C6BD2F1F3E20808684" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_643B8C25BBD34AD0B405B27E06E03698" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7A5EA42289F94648877FA695EB1853CE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8292EFFD84EF46C6BD2F1F3E20808684" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_92336612AC7D083F97ED302BB7674A2D" + "OwnerKey" = "8:_191525A919DD46AD8D70B7735EE4F451" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_92336612AC7D083F97ED302BB7674A2D" + "OwnerKey" = "8:_3986DA1502244FFBB04A66472E74633B" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9A3A0F1784E448538A42AE8722C1FE40" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9AF33A7F4DD64BB58CD561EC8145A8A3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9C164F1F2FC0451CA2814BE9BAD532FB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B0715A326B76440C90A71D7BB2B61C52" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E35F46E021184676375C6223ED1BDFCF" + "OwnerKey" = "8:_191525A919DD46AD8D70B7735EE4F451" + "MsmSig" = "8:_UNDEFINED" + } + } + "Configurations" + { + "Debug" + { + "DisplayName" = "8:Debug" + "IsDebugOnly" = "11:TRUE" + "IsReleaseOnly" = "11:FALSE" + "OutputFilename" = "8:Debug\\authtokenclient_msm.msm" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:1" + } + "Release" + { + "DisplayName" = "8:Release" + "IsDebugOnly" = "11:FALSE" + "IsReleaseOnly" = "11:TRUE" + "OutputFilename" = "8:Release\\authtokenclient_msm.msm" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:1" + } + } + "Deployable" + { + "CustomAction" + { + } + "DefaultFeature" + { + "Name" = "8:DefaultFeature" + "Title" = "8:" + "Description" = "8:" + } + "File" + { + "{A582A373-4685-4296-BEFE-614B80A702C3}:_22FDEF26EDCE4831A621BB20C7EB4508" + { + "SourcePath" = "8:..\\..\\..\\include\\casa_c_authtoken.h" + "TargetName" = "8:casa_c_authtoken.h" + "Tag" = "8:" + "Folder" = "8:_9568FCF514C14B54BAB7D1D5D183D3C5" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_313DE095D13281AF91A64E3F3D472413" + { + "SourcePath" = "8:Secur32.dll" + "TargetName" = "8:Secur32.dll" + "Tag" = "8:" + "Folder" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_643B8C25BBD34AD0B405B27E06E03698" + { + "SourcePath" = "8:..\\..\\..\\client\\mechanisms\\krb5\\windows\\Krb5Authenticate.conf" + "TargetName" = "8:Krb5Authenticate.conf" + "Tag" = "8:" + "Folder" = "8:_DEA051CA331E4FEA83D99711FB584664" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_92336612AC7D083F97ED302BB7674A2D" + { + "SourcePath" = "8:micasa.dll" + "TargetName" = "8:micasa.dll" + "Tag" = "8:" + "Folder" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_9A3A0F1784E448538A42AE8722C1FE40" + { + "SourcePath" = "8:..\\..\\..\\client\\windows\\authtoken.lib" + "TargetName" = "8:authtoken.lib" + "Tag" = "8:" + "Folder" = "8:_01897726E7804A3B875B67A1C2692147" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_9AF33A7F4DD64BB58CD561EC8145A8A3" + { + "SourcePath" = "8:..\\..\\..\\include\\windows\\casa_c_authtoken_ex.h" + "TargetName" = "8:casa_c_authtoken_ex.h" + "Tag" = "8:" + "Folder" = "8:_9568FCF514C14B54BAB7D1D5D183D3C5" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_9C164F1F2FC0451CA2814BE9BAD532FB" + { + "SourcePath" = "8:..\\..\\..\\client\\client.conf" + "TargetName" = "8:client.conf" + "Tag" = "8:" + "Folder" = "8:_24DA90392089420889094EC07EB4F28C" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_B0715A326B76440C90A71D7BB2B61C52" + { + "SourcePath" = "8:..\\..\\..\\client\\mechanisms\\pwd\\windows\\PwdAuthenticate.conf" + "TargetName" = "8:PwdAuthenticate.conf" + "Tag" = "8:" + "Folder" = "8:_DEA051CA331E4FEA83D99711FB584664" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_E35F46E021184676375C6223ED1BDFCF" + { + "SourcePath" = "8:WINHTTP.dll" + "TargetName" = "8:WINHTTP.dll" + "Tag" = "8:" + "Folder" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + } + "FileType" + { + } + "Folder" + { + "{B4CE2BB7-2D9F-4E14-A952-99DFEBF520A8}:_8E0BBDD021EA45308BD98380F28EB7F6" + { + "Name" = "8:#1927" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:GAC" + "Folders" + { + } + } + "{78BAF5CE-F2E5-45BE-83BC-DB6AF387E941}:_DB481DA18FE347988F44E459AD84EDE9" + { + "Name" = "8:#1912" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:ProgramFilesFolder" + "Folders" + { + "{F27BD5C5-A65D-4608-96D4-7C5DA1F76302}:_00A3E8736D134835AD0537E00F100987" + { + "Name" = "8:Novell" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_6F4D982C87CA4DF991766D49335B6669" + "Folders" + { + "{F27BD5C5-A65D-4608-96D4-7C5DA1F76302}:_7911DA52FBB24F3DB6BAF4B8BD9E57BF" + { + "Name" = "8:CASA" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_5C00DF0C10DE42D887AF2473050E45C9" + "Folders" + { + "{F27BD5C5-A65D-4608-96D4-7C5DA1F76302}:_01897726E7804A3B875B67A1C2692147" + { + "Name" = "8:lib" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_9CB2846430C044D4A85E07E79ED81EC6" + "Folders" + { + } + } + "{F27BD5C5-A65D-4608-96D4-7C5DA1F76302}:_9568FCF514C14B54BAB7D1D5D183D3C5" + { + "Name" = "8:include" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_E75CE2ED8E574BD6BDBF415E739623A2" + "Folders" + { + } + } + "{F27BD5C5-A65D-4608-96D4-7C5DA1F76302}:_B639068B7BE1480495ADAF8B2461A075" + { + "Name" = "8:etc" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_B04A2882FFAA4A959983F9D9750066CB" + "Folders" + { + "{F27BD5C5-A65D-4608-96D4-7C5DA1F76302}:_24DA90392089420889094EC07EB4F28C" + { + "Name" = "8:auth" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_AE09329FDCD54A98A0A90DDD67FE7E50" + "Folders" + { + "{F27BD5C5-A65D-4608-96D4-7C5DA1F76302}:_DEA051CA331E4FEA83D99711FB584664" + { + "Name" = "8:mechanisms" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_DA97A45985F64232A6DEAD78C88EDEE5" + "Folders" + { + } + } + } + } + } + } + } + } + } + } + } + } + "{78BAF5CE-F2E5-45BE-83BC-DB6AF387E941}:_E092F841E4D04920B053C3F6A5151BA2" + { + "Name" = "8:#1914" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:SystemFolder" + "Folders" + { + } + } + "{29CD8198-A6F0-4B93-8B90-AC03CFEAD328}:_F5F5F604B81645F8B6463F7A7D6A53AD" + { + "DefaultLocation" = "8:[ProgramFilesFolder]\\novell\\casa\\lib" + "DisplayName" = "8:Module Retargetable Folder" + "Description" = "8:" + "Name" = "8:Module Retargetable Folder" + "AlwaysCreate" = "11:TRUE" + "Condition" = "8:" + "Transitive" = "11:TRUE" + "Property" = "8:NEWRETARGETABLEPROPERTY1" + "Folders" + { + } + } + } + "Sequences" + { + } + "MergeModule" + { + "{35A69C6E-5BA4-440D-803D-762B59A45393}:_472FEAD17E7B45FF92E93D80B3379C47" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:TRUE" + "SourcePath" = "8:dotnetfxredist_x86.msm" + "LanguageId" = "3:1033" + "Exclude" = "11:FALSE" + "Folder" = "8:" + "Feature" = "8:" + "IsolateTo" = "8:" + } + } + "Module" + { + "ModuleSignature" = "8:MergeModule.375AEECA1C3A4EC3AF37E3E5BE6711DD" + "Version" = "8:1.0.0.0" + "Title" = "8:authtokenclient_msm" + "Subject" = "8:" + "Author" = "8:Novell" + "Keywords" = "8:" + "Comments" = "8:" + "SearchPath" = "8:" + "UseSystemSearchPath" = "11:TRUE" + } + "ProjectOutput" + { + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_191525A919DD46AD8D70B7735EE4F451" + { + "SourcePath" = "8:..\\..\\..\\client\\windows\\Debug\\authtoken.dll" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{7BD9A5DB-DE7D-40B7-A397-04182DC2F632}" + "ShowKeyOutput" = "11:FALSE" + "ExcludeFilters" + { + } + } + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_3986DA1502244FFBB04A66472E74633B" + { + "SourcePath" = "8:..\\..\\..\\client\\mechanisms\\pwd\\windows\\Debug\\pwmech.dll" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{5499F624-F371-4559-B4C2-A484BCE892FD}" + "ShowKeyOutput" = "11:FALSE" + "ExcludeFilters" + { + } + } + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_7A5EA42289F94648877FA695EB1853CE" + { + "SourcePath" = "8:..\\..\\..\\client\\mechanisms\\krb5\\windows\\Debug\\krb5mech.dll" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_F5F5F604B81645F8B6463F7A7D6A53AD" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{5499F624-F371-4559-B4C2-A484BCE892FD}" + "ShowKeyOutput" = "11:FALSE" + "ExcludeFilters" + { + } + } + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_8292EFFD84EF46C6BD2F1F3E20808684" + { + "SourcePath" = "8:..\\..\\..\\client\\csharp\\Novell.Casa.Authtoken\\obj\\Debug\\Novell.Casa.Client.Auth.dll" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_8E0BBDD021EA45308BD98380F28EB7F6" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{1BA1FC97-5AF1-4506-A7FD-EBFD46D361A0}" + "ShowKeyOutput" = "11:TRUE" + "ExcludeFilters" + { + } + } + } + "Registry" + { + "HKLM" + { + "Keys" + { + } + } + "HKCU" + { + "Keys" + { + } + } + "HKCR" + { + "Keys" + { + } + } + "HKU" + { + "Keys" + { + } + } + "HKPU" + { + "Keys" + { + } + } + } + "Shortcut" + { + } + } +}