diff --git a/CASA-auth-token/native/AUTHORS b/CASA-auth-token/native/AUTHORS new file mode 100644 index 00000000..ba13017c --- /dev/null +++ b/CASA-auth-token/native/AUTHORS @@ -0,0 +1,2 @@ +Juan Carlos Luciani - jluciani@novell.com + diff --git a/CASA-auth-token/native/COPYING b/CASA-auth-token/native/COPYING new file mode 100644 index 00000000..b0ab9a23 --- /dev/null +++ b/CASA-auth-token/native/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/native/ChangeLog b/CASA-auth-token/native/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/CASA-auth-token/native/Makefile.am b/CASA-auth-token/native/Makefile.am new file mode 100644 index 00000000..84e5e7ff --- /dev/null +++ b/CASA-auth-token/native/Makefile.am @@ -0,0 +1,38 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = server package + +DIST_SUBDIRS = include server package + +EXTRA_DIST = autogen.sh + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C package $@ + +clean-local: + if [ -d lib ]; then rm -rf lib; fi + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/native/NEWS b/CASA-auth-token/native/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/CASA-auth-token/native/README b/CASA-auth-token/native/README new file mode 100644 index 00000000..3abc9805 --- /dev/null +++ b/CASA-auth-token/native/README @@ -0,0 +1,90 @@ +/*********************************************************************** + * + * README for auth_token + * + ***********************************************************************/ + +INTRODUCTION + +CASA-auth-token is an authentication token infrastructure with support for multiple +authentication mechanisms with an emphasis on providing a scalable single +sign-on solution. + +A key feature of auth_token is that its authentication tokens contain identity +information about the entity being authenticated. This information is made available +to the consuming services. The amount of information contained in the tokens is +configured on a per-service basis. Because of this feature, we say that CASA-auth-token +projects an "Authenticated Identity". + +ARCHITECTURE COMPONENTS + +The infrastructure provided by auth_token consists of client and server components. + +The client components of auth_token consists of a Client Engine, Get Authentication +Token API, Authentication Token Cache, and Authentication Mechanism plug-ins. + +The server components of auth_token consists of an Authentication Token Service, a +Verify Authentication Token API, a JAAS module, a PAM module, and an Apache Authentication +Provider module. The Authentication Token Service makes use of Authentication Mechanism +plug-ins, an Identity Data Store Abstraction Layer, and of Identity Token Providers. + +SECURITY FEATURES AND DATA FLOW + +Communications between the Client Engine and the Authentication Token Service (ATS) +occur over HTTPS. When a client desires to obtain an Authentication Token to access +a particular service it contacts an ATS which then proceeds to inform the client about +the Authentication Policy configured for the service. The policy contains information +about authentication mechanisms supported as well as information about the types of +credentials that the client can utilize to authenticate to the ATS. Once the client +receives the Authentication Policy, it then decides what authentication mechanism to +utilize to authenticate to the ATS based on the available authentication mechanisms +plug-ins as well as the available credentials. During the authentication process, the +ATS associates an identity with the entity being authenticated. The result of this +resolution is saved in a Session Token which is then sent to the client where it is +cached. Once the client is authenticated to the ATS, it then requests Authentication +Tokens from it using the obtained Session Token. When an ATS receives a request for +an Authentication Token, it then verifies the validity of the received Session Token +and then it creates the appropriate Identity Token for the target service which it then +embeds within the Authentication Token. The indentity information contained in the +Identity Token as well as the type of Identity Token utilized depends on what is +configured for the tatget service. + +Session Tokens and Authentication Tokens are signed by the issuing ATS using Signing +Certificates. Session Tokens and Authentication Tokens have a Lifetime Value associated +with them. Token verification involves verifying the token signatures, verifying that +the tokens where signed by a trusted entity, and verifying that the token lifetime has +not been exceeeded. + +The auth_token client/service protocol allows for the authentication of the client entity. +auth_token relies in the server authentication mechanisms of SSL to verify the identity +of the ATS. + +IMPLEMENTATION STRATEGY AND CURRENT STATUS + +auth_token is currently under development and is not ready to be used in production. +The implementation strategy has been to first complete the framework with all of its +modules, APIs, and packaging to allow application writters to start developing to it. +Once this is done, then the implementation focus will switch to completing the plumbing. + +As of this time, a lot of the framework has been completed and there are sample +applications that can be utilized to exercise it. For a more complete picture of where +we are, look at the various TODO lists present in the child folders. + +The schedule for completing auth_token is agressive. + +SECURITY CONSIDERATIONS + +CASA Authentication Tokens when compromised can be used to either impersonate +a user or to obtain identity information about the user. Because of this it is +important that the tokens be secured by applications making use of them. It is +recommended that the tokens be transmitted using SSL. + + + + + + + + + + diff --git a/CASA-auth-token/native/TODO b/CASA-auth-token/native/TODO new file mode 100644 index 00000000..4bc8d36e --- /dev/null +++ b/CASA-auth-token/native/TODO @@ -0,0 +1,17 @@ +/*********************************************************************** + * + * TODO for auth_token + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for auth_token. + +Note: There are TODO lists under each auth_token component. This file just +details outstanding items at the project level. + +OUTSTANDING ITEMS + +- Plug-in auth_token into the CASA make system. + diff --git a/CASA-auth-token/native/auth.sln b/CASA-auth-token/native/auth.sln new file mode 100644 index 00000000..5eb33a93 --- /dev/null +++ b/CASA-auth-token/native/auth.sln @@ -0,0 +1,60 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "client\client.vcproj", "{7BD9A5DB-DE7D-40B7-A397-04182DC2F632}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "client\test\test.vcproj", "{6034EBF1-0838-45C4-A538-A41A31EC8F46}" + ProjectSection(ProjectDependencies) = postProject + {7BD9A5DB-DE7D-40B7-A397-04182DC2F632} = {7BD9A5DB-DE7D-40B7-A397-04182DC2F632} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "krb5", "client\mechanisms\krb5\krb5.vcproj", "{5499F624-F371-4559-B4C2-A484BCE892FD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pwd", "client\mechanisms\pwd\pwd.vcproj", "{5499F624-F371-4559-B4C2-A484BCE892FD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "authtokenclient_msm", "client\authtokenclient_msm\authtokenclient_msm.vdproj", "{70ED319E-F496-4F07-878C-1921426DD399}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "authtokenclient_msi", "client\authtokenclient_msi\authtokenclient_msi.vdproj", "{AA014EB3-8AD3-49B8-92E3-F8AA0FBCEE9B}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {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 + {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 + {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 + {70ED319E-F496-4F07-878C-1921426DD399}.Debug.ActiveCfg = Debug + {70ED319E-F496-4F07-878C-1921426DD399}.Debug.Build.0 = Debug + {70ED319E-F496-4F07-878C-1921426DD399}.Release.ActiveCfg = Release + {70ED319E-F496-4F07-878C-1921426DD399}.Release.Build.0 = Release + {AA014EB3-8AD3-49B8-92E3-F8AA0FBCEE9B}.Debug.ActiveCfg = Debug + {AA014EB3-8AD3-49B8-92E3-F8AA0FBCEE9B}.Release.ActiveCfg = Release + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/CASA-auth-token/native/autogen.sh b/CASA-auth-token/native/autogen.sh new file mode 100755 index 00000000..19ad55ec --- /dev/null +++ b/CASA-auth-token/native/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/native/client/README b/CASA-auth-token/native/client/README new file mode 100644 index 00000000..66ed0620 --- /dev/null +++ b/CASA-auth-token/native/client/README @@ -0,0 +1,67 @@ +/*********************************************************************** + * + * 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/opt/novell/CASA/authtoken.d/modules.d. +The path to this folder under Windows is \Program Files\novell\CASA\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/native/client/TODO b/CASA-auth-token/native/client/TODO new file mode 100644 index 00000000..a96f51d3 --- /dev/null +++ b/CASA-auth-token/native/client/TODO @@ -0,0 +1,18 @@ +/*********************************************************************** + * + * TODO for libcasa_c_authtoken + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for libcasa_c_authtoken. + +OUTSTANDING ITEMS + +- Implementation of Linux specific code. +- Re-structure the token cache to differentiate between Session Tokens and Authentication Tokens. +- Use the CASA cache as the token store. +- Switch Client/Server protocol to use SOAP Messages. +- Enable communications over HTTPS instead of over HTTP. + diff --git a/CASA-auth-token/native/client/authmech.c b/CASA-auth-token/native/client/authmech.c new file mode 100644 index 00000000..991a64bb --- /dev/null +++ b/CASA-auth-token/native/client/authmech.c @@ -0,0 +1,339 @@ +/*********************************************************************** + * + * 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, + INOUT char **ppAuthToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + AuthTokenIf *pAuthTokenIf; + + + 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, + 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, + 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/native/client/authmsg.c b/CASA-auth-token/native/client/authmsg.c new file mode 100644 index 00000000..96329276 --- /dev/null +++ b/CASA-auth-token/native/client/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 = %08X\n", 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, + AuthRespStartElementHandler, + AuthRespEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, 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/native/client/authpolicy.c b/CASA-auth-token/native/client/authpolicy.c new file mode 100644 index 00000000..b69ce2b0 --- /dev/null +++ b/CASA-auth-token/native/client/authpolicy.c @@ -0,0 +1,801 @@ +/*********************************************************************** + * + * 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: + + // 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: + + // 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: + + // 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 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, + &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, + AuthPolicyStartElementHandler, + AuthPolicyEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, 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/native/client/authtokenclient_msi/authtokenclient_msi.vdproj b/CASA-auth-token/native/client/authtokenclient_msi/authtokenclient_msi.vdproj new file mode 100644 index 00000000..07135092 --- /dev/null +++ b/CASA-auth-token/native/client/authtokenclient_msi/authtokenclient_msi.vdproj @@ -0,0 +1,694 @@ +"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:_C9C2CAF6FE7A41938101D843D18673B7" + "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" + { + } + } + "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:{197B9AC3-1D6A-4EA8-AC8A-C7695F57A28F}" + "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}:_7F0506CDE05C426E9A69E1F0F6A1B9A4" + { + "Sequence" = "3:200" + "DisplayName" = "8:Installation Folder" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdFolderDlg.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}:_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" + { + } + "ProjectOutput" + { + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_C9C2CAF6FE7A41938101D843D18673B7" + { + "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:{70ED319E-F496-4F07-878C-1921426DD399}" + "ShowKeyOutput" = "11:TRUE" + "ExcludeFilters" + { + } + "KeyOutputModule" + { + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:..\\authtokenclient_msm\\Release\\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/native/client/authtokenclient_msm/authtokenclient_msm.vdproj b/CASA-auth-token/native/client/authtokenclient_msm/authtokenclient_msm.vdproj new file mode 100644 index 00000000..206f67ca --- /dev/null +++ b/CASA-auth-token/native/client/authtokenclient_msm/authtokenclient_msm.vdproj @@ -0,0 +1,542 @@ +"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:_0C000CB7C5FA4E2BB6A6CB1C204EABA6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0C0B5ECE6E9C47F1A1F13B58141B5DC8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1231718055D14020BF756DCF44D2BF22" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_313DE095D13281AF91A64E3F3D472413" + "OwnerKey" = "8:_DB9D7F0710B44F858325E4EFCCB2EEB3" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_677B016062384F4C8A73EC952CBCFD76" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_753EBE1EB0DC420C88ED02E5A978FF35" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_767D1F0838D74B6C86C5E9C14643AE48" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_92336612AC7D083F97ED302BB7674A2D" + "OwnerKey" = "8:_9A2FC85FE99C48E8AD1E4813BE33A03A" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9A2FC85FE99C48E8AD1E4813BE33A03A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DB9D7F0710B44F858325E4EFCCB2EEB3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FE85A5D48B5A23F3077871E9FD2378DE" + "OwnerKey" = "8:_0C0B5ECE6E9C47F1A1F13B58141B5DC8" + "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}:_0C000CB7C5FA4E2BB6A6CB1C204EABA6" + { + "SourcePath" = "8:..\\mechanisms\\pwd\\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}:_1231718055D14020BF756DCF44D2BF22" + { + "SourcePath" = "8:..\\mechanisms\\krb5\\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}:_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:FALSE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_677B016062384F4C8A73EC952CBCFD76" + { + "SourcePath" = "8:..\\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}:_753EBE1EB0DC420C88ED02E5A978FF35" + { + "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}:_767D1F0838D74B6C86C5E9C14643AE48" + { + "SourcePath" = "8:..\\..\\..\\include\\casa_status.h" + "TargetName" = "8:casa_status.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}:_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:FALSE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{A582A373-4685-4296-BEFE-614B80A702C3}:_FE85A5D48B5A23F3077871E9FD2378DE" + { + "SourcePath" = "8:WINHTTP.dll" + "TargetName" = "8:WINHTTP.dll" + "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:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + } + "FileType" + { + } + "Folder" + { + "{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" + { + } + } + } + } + } + } + } + } + } + } + } + } + "{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" + { + } + "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}:_0C0B5ECE6E9C47F1A1F13B58141B5DC8" + { + "SourcePath" = "8:..\\windows\\Debug\\authtoken.dll" + "TargetName" = "8:" + "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:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{7BD9A5DB-DE7D-40B7-A397-04182DC2F632}" + "ShowKeyOutput" = "11:FALSE" + "ExcludeFilters" + { + } + } + "{8062640A-2EEE-46E9-AB67-688E9A886E9F}:_9A2FC85FE99C48E8AD1E4813BE33A03A" + { + "SourcePath" = "8:..\\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}:_DB9D7F0710B44F858325E4EFCCB2EEB3" + { + "SourcePath" = "8:..\\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" + { + } + } + } + "Registry" + { + "HKLM" + { + "Keys" + { + } + } + "HKCU" + { + "Keys" + { + } + } + "HKCR" + { + "Keys" + { + } + } + "HKU" + { + "Keys" + { + } + } + "HKPU" + { + "Keys" + { + } + } + } + "Shortcut" + { + } + } +} diff --git a/CASA-auth-token/native/client/client.vcproj b/CASA-auth-token/native/client/client.vcproj new file mode 100644 index 00000000..842d8e62 --- /dev/null +++ b/CASA-auth-token/native/client/client.vcproj @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/native/client/config.c b/CASA-auth-token/native/client/config.c new file mode 100644 index 00000000..fa6c601b --- /dev/null +++ b/CASA-auth-token/native/client/config.c @@ -0,0 +1,685 @@ +/*********************************************************************** + * + * 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(1, "-GetConfigInterface- Unable to open config file, errno = %d\n", errno); + } + } + 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/native/client/config_if.h b/CASA-auth-token/native/client/config_if.h new file mode 100644 index 00000000..0cdf31ce --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/engine.c b/CASA-auth-token/native/client/engine.c new file mode 100644 index 00000000..31c8f5ff --- /dev/null +++ b/CASA-auth-token/native/client/engine.c @@ -0,0 +1,663 @@ +/*********************************************************************** + * + * 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 ]=============================================== + +//===[ Global variables ]================================================== + +// +// Debug tracing level +// +int DebugLevel = 0; + +// +// Operating parameter +// +bool secureRpcSetting = false; +int retryLifetime = DEFAULT_RETRY_LIFETIME; + + +//++======================================================================= +static +CasaStatus +ObtainSessionToken( + IN RpcSession *pRpcSession, + IN AuthPolicy *pAuthPolicy, + 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); + 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 + { + // Release auth cache entry reference + ReleaseAuthCacheEntry(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); + if (pCacheEntry == NULL) + { + // Get authentication mechanism token + retStatus = GetAuthMechToken(pAuthContext, &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; + } + + // Create a cache entry for the auth context + pCacheEntry = CreateSessionTokenCacheEntry(pAuthContext->pContext); + if (pCacheEntry) + { + char *pReqMsg = NULL; + char *pRespMsg = NULL; + int respLen; + int cacheEntryLifetime = retryLifetime; // Initialize to retry in case of failure + + // Authenticate to the ATS + pReqMsg = BuildAuthenticateMsg(pAuthContext, pAuthMechToken); + if (pReqMsg) + { + // Issue rpc + retStatus = Rpc(pRpcSession, + "Authenticate", + secureRpcSetting, + 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->pToken = pAuthenticateResp->pToken; + pAuthenticateResp->pToken = NULL; // To keep us from freeing the buffer + cacheEntryLifetime = pAuthenticateResp->tokenLifetime; + + // 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 (CASA_SUCCESS(retStatus) + || CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE) + { + pCacheEntry->status = retStatus; + AddEntryToAuthCache(pCacheEntry, cacheEntryLifetime); + } + + // Release the cache entry if the resulting status is not successful + if (!CASA_SUCCESS(retStatus)) + { + // Release auth cache entry reference + ReleaseAuthCacheEntry(pCacheEntry); + } + } + else + { + DbgTrace(0, "-ObtainSessionToken- Cache entry creation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Free up the buffer associated with the authentication mechanism token + free(pAuthMechToken); + } + else + { + // Release auth cache entry reference + ReleaseAuthCacheEntry(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->pToken) + 1); + if (*ppSessionToken) + { + // Copy the token onto the allocated buffer + strcpy(*ppSessionToken, pCacheEntry->pToken); + } + else + { + DbgTrace(0, "-ObtainSessionToken- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Release auth cache entry reference + ReleaseAuthCacheEntry(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) +// +// 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(pHostName); + 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, pHostName); + if (pReqMsg) + { + // Issue rpc + retStatus = Rpc(pRpcSession, + "GetAuthPolicy", + secureRpcSetting, + 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, &pSessionToken); + if (CASA_SUCCESS(retStatus)) + { + // Request auth token for the service + free(pReqMsg); + pReqMsg = BuildGetAuthTokenMsg(pServiceName, pHostName, pSessionToken); + if (pReqMsg) + { + // Free the previous response msg buffer + free(pRespMsg); + pRespMsg = NULL; + + // Issue rpc + retStatus = Rpc(pRpcSession, + "GetAuthToken", + secureRpcSetting, + 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 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 = CASA_STATUS_SUCCESS; + AuthCacheEntry *pCacheEntry; + char *pNormalizedHostName; + + DbgTrace(1, "-ObtainAuthToken- Start\n", 0); + + // Verify the input parameters + if (pServiceName == NULL + || pHostName == NULL + || pAuthTokenBufLen == NULL + || (*pAuthTokenBufLen != 0 && pAuthTokenBuf == NULL)) + { + DbgTrace(0, "-ObtainAuthToken- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Normalize the host name + pNormalizedHostName = NormalizeHostName(pHostName); + if (pNormalizedHostName) + { + // Start user process synchronization + AcquireUserMutex(); + + // Try to find a cache entry for the service + pCacheEntry = FindAuthTokenEntryInCache(pServiceName, pNormalizedHostName); + if (pCacheEntry == NULL) + { + // No entry found in the cache, create one. + pCacheEntry = CreateAuthTokenCacheEntry(pServiceName, pNormalizedHostName); + if (pCacheEntry) + { + int cacheEntryLifetime = retryLifetime; // Initialize to retry in case of failure + + // Cache entry created, now try to obtain auth token from the CASA Server + retStatus = ObtainAuthTokenFromServer(pServiceName, + pNormalizedHostName, + &pCacheEntry->pToken, + &cacheEntryLifetime); + + // 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->status = retStatus; + AddEntryToAuthCache(pCacheEntry, cacheEntryLifetime); + } + + // Release the cache entry if the resulting status is not successful + if (!CASA_SUCCESS(retStatus)) + { + // Release auth cache entry reference + ReleaseAuthCacheEntry(pCacheEntry); + } + } + else + { + DbgTrace(0, "-ObtainAuthToken- Cache entry creation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + 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)) + { + // Release auth cache entry reference + ReleaseAuthCacheEntry(pCacheEntry); + } + } + + // Try to return auth token if we have one to return + if (CASA_SUCCESS(retStatus)) + { + int tokenLen = (int) strlen(pCacheEntry->pToken) + 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 + strcpy(pAuthTokenBuf, pCacheEntry->pToken); + } + else + { + DbgTrace(0, "-ObtainAuthToken- 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; + + // Release auth cache entry reference + ReleaseAuthCacheEntry(pCacheEntry); + } + + // Stop user process synchronization + ReleaseUserMutex(); + + // Free the space allocated for the normalized host name + free(pNormalizedHostName); + } + else + { + DbgTrace(0, "-ObtainAuthToken- Host name normalization failed\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + +exit: + + DbgTrace(1, "-ObtainAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +InitializeLibrary(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "-InitializeLibrary- Start\n", 0); + + // Create user synchronization mutex + if (CreateUserMutex() == 0) + { + // Initialize the auth cache + if (CASA_SUCCESS(InitializeAuthCache())) + { + // Initialize the host name normalization + if (CASA_SUCCESS(InitializeHostNameNormalization())) + { + // Success + retStatus = 0; + } + else + { + DbgTrace(0, "-InitializeLibrary- Error initializing host name normalization\n", 0); + } + } + else + { + DbgTrace(0, "-InitializeLibrary- Error initializing the auth cache\n", 0); + } + } + else + { + DbgTrace(0, "-InitializeLibrary- Error creating mutex for the user\n", 0); + } + + DbgTrace(1, "-InitializeLibrary- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/client/getpolicymsg.c b/CASA-auth-token/native/client/getpolicymsg.c new file mode 100644 index 00000000..5b568cc8 --- /dev/null +++ b/CASA-auth-token/native/client/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 char *pServiceName, + IN 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 = %08X\n", 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, + GetAuthPolicyRespStartElementHandler, + GetAuthPolicyRespEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, 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/native/client/gettokenmsg.c b/CASA-auth-token/native/client/gettokenmsg.c new file mode 100644 index 00000000..e25a7218 --- /dev/null +++ b/CASA-auth-token/native/client/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 char *pServiceName, + IN 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 = %08X\n", 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, + GetAuthTokenRespStartElementHandler, + GetAuthTokenRespEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, 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/native/client/internal.h b/CASA-auth-token/native/client/internal.h new file mode 100644 index 00000000..bd342a90 --- /dev/null +++ b/CASA-auth-token/native/client/internal.h @@ -0,0 +1,369 @@ +/*********************************************************************** + * + * 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; + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +extern char mechConfigFolder[]; + +extern char pathCharString[]; + + + +//===[ External prototypes ]=============================================== + +// +// Functions exported by engine.c +// + +extern +int +InitializeLibrary(void); + +// +// Functions exported by authmech.c +// + +extern +CasaStatus +GetAuthMechToken( + IN AuthContext *pAuthContext, + INOUT char **ppAuthMechToken); + +// +// Functions exported by getpolicymsg.c +// + +extern +char* +BuildGetAuthPolicyMsg( + IN char *pServiceName, + IN 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 char *pServiceName, + IN 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); + +extern +AuthCacheEntry* +CreateAuthTokenCacheEntry( + IN const char *pCacheKey, + IN const char *pGroupOrHostName); + +extern +void +ReleaseAuthCacheEntry( + IN AuthCacheEntry *pEntry); + +extern void +IncAuthCacheEntryRefCount( + IN AuthCacheEntry *pEntry); + +extern +AuthCacheEntry* +FindSessionTokenEntryInCache( + IN const char *pCacheKey); + +extern +AuthCacheEntry* +FindAuthTokenEntryInCache( + IN const char *pCacheKey, + IN const char *pGroupOrHostName); + +extern +void +AddEntryToAuthCache( + IN AuthCacheEntry *pEntry, + IN int entryLifetime); + +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(void); + +extern +void +AcquireUserMutex(void); + +extern +void +ReleaseUserMutex(void); + +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 char *pHostName); + +extern +void +CloseRpcSession( + IN RpcSession *pSession); + +extern +CasaStatus +Rpc( + IN RpcSession *pSession, + IN char *pMethod, + IN bool secure, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen); + +// +// 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); + +extern +int +dtoul( + IN const char *cp, + IN const int len); + + +//========================================================================= + +#endif // _INTERNAL_H_ + diff --git a/CASA-auth-token/native/client/mech_if.h b/CASA-auth-token/native/client/mech_if.h new file mode 100644 index 00000000..285d70a8 --- /dev/null +++ b/CASA-auth-token/native/client/mech_if.h @@ -0,0 +1,177 @@ +/*********************************************************************** + * + * 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, + 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. +// +// 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/native/client/mechanisms/krb5/Krb5Authenticate.conf b/CASA-auth-token/native/client/mechanisms/krb5/Krb5Authenticate.conf new file mode 100644 index 00000000..df843e9f --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/krb5/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/native/client/mechanisms/krb5/README b/CASA-auth-token/native/client/mechanisms/krb5/README new file mode 100644 index 00000000..6b5f03b1 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/krb5/README @@ -0,0 +1,30 @@ +/*********************************************************************** + * + * 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/native/client/mechanisms/krb5/TODO b/CASA-auth-token/native/client/mechanisms/krb5/TODO new file mode 100644 index 00000000..c7b55ce1 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/krb5/TODO @@ -0,0 +1,14 @@ +/*********************************************************************** + * + * TODO for krb5mech + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for krb5mech. + +OUTSTANDING ITEMS + +- Implementation of Linux specific code. + diff --git a/CASA-auth-token/native/client/mechanisms/krb5/interface.c b/CASA-auth-token/native/client/mechanisms/krb5/interface.c new file mode 100644 index 00000000..2fbdf3f4 --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/krb5/internal.h b/CASA-auth-token/native/client/mechanisms/krb5/internal.h new file mode 100644 index 00000000..dad21ef1 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/krb5/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 "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, + 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/native/client/mechanisms/krb5/krb5.vcproj b/CASA-auth-token/native/client/mechanisms/krb5/krb5.vcproj new file mode 100644 index 00000000..964d71f8 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/krb5/krb5.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/native/client/mechanisms/krb5/util.c b/CASA-auth-token/native/client/mechanisms/krb5/util.c new file mode 100644 index 00000000..90454c7a --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/krb5/windows/dllsup.c b/CASA-auth-token/native/client/mechanisms/krb5/windows/dllsup.c new file mode 100644 index 00000000..1fbf8cc8 --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/krb5/windows/get.c b/CASA-auth-token/native/client/mechanisms/krb5/windows/get.c new file mode 100644 index 00000000..a3ac6000 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/krb5/windows/get.c @@ -0,0 +1,272 @@ +/*********************************************************************** + * + * 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, + 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. +// +// 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 + || pMechInfo == 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; + } + + // 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: + + 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/native/client/mechanisms/krb5/windows/krb5mech.def b/CASA-auth-token/native/client/mechanisms/krb5/windows/krb5mech.def new file mode 100644 index 00000000..1605afcf --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/krb5/windows/platform.c b/CASA-auth-token/native/client/mechanisms/krb5/windows/platform.c new file mode 100644 index 00000000..869b581c --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/krb5/windows/platform.h b/CASA-auth-token/native/client/mechanisms/krb5/windows/platform.h new file mode 100644 index 00000000..1b3f0f7f --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/pwd/PwdAuthenticate.conf b/CASA-auth-token/native/client/mechanisms/pwd/PwdAuthenticate.conf new file mode 100644 index 00000000..171f06e0 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/pwd/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/native/client/mechanisms/pwd/README b/CASA-auth-token/native/client/mechanisms/pwd/README new file mode 100644 index 00000000..12f170d6 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/pwd/README @@ -0,0 +1,27 @@ +/*********************************************************************** + * + * 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/native/client/mechanisms/pwd/TODO b/CASA-auth-token/native/client/mechanisms/pwd/TODO new file mode 100644 index 00000000..cf307b20 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/pwd/TODO @@ -0,0 +1,14 @@ +/*********************************************************************** + * + * TODO for pwmech + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for pwmech. + +OUTSTANDING ITEMS + +- Implementation of Linux specific code. + diff --git a/CASA-auth-token/native/client/mechanisms/pwd/get.c b/CASA-auth-token/native/client/mechanisms/pwd/get.c new file mode 100644 index 00000000..f2b88546 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/pwd/get.c @@ -0,0 +1,359 @@ +/*********************************************************************** + * + * 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, + INOUT char **ppUsername, + INOUT char **ppPassword) +// +// Arguments: +// pRealm - +// The realm to which the credentials apply. +// +// 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; + int32_t credtype = SSCS_CRED_TYPE_BASIC_F; + SSCS_BASIC_CREDENTIAL credential = {0}; + SSCS_SECRET_ID_T secretId = {0}; + SSCS_SECRET_ID_T sharedSecretId = {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(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, + NULL); + 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(secretId.id, "Desktop"); + rcode = miCASAGetCredential(0, + &secretId, + NULL, + &credtype, + &credential, + NULL); + } + } + 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(credential.username) + 1); + if (pUsername) + { + // Copy the username into the buffer that we will be returning + strcpy(pUsername, credential.username); + + // Allocate a buffer to return the password + pPassword = (char*) malloc(strlen(credential.password) + 1); + if (pPassword) + { + // Copy the password into the buffer that we will be returning + strcpy(pPassword, credential.password); + + // 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); + } + } + + // 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, + 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. +// +// 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 + || pMechInfo == 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, &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; +} + + +//++======================================================================= +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/native/client/mechanisms/pwd/interface.c b/CASA-auth-token/native/client/mechanisms/pwd/interface.c new file mode 100644 index 00000000..2fbdf3f4 --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/pwd/internal.h b/CASA-auth-token/native/client/mechanisms/pwd/internal.h new file mode 100644 index 00000000..3ac0c0cd --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/pwd/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 +#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, + 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/native/client/mechanisms/pwd/pwd.vcproj b/CASA-auth-token/native/client/mechanisms/pwd/pwd.vcproj new file mode 100644 index 00000000..ebc6fd50 --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/pwd/pwd.vcproj @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/native/client/mechanisms/pwd/util.c b/CASA-auth-token/native/client/mechanisms/pwd/util.c new file mode 100644 index 00000000..90454c7a --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/pwd/windows/dllsup.c b/CASA-auth-token/native/client/mechanisms/pwd/windows/dllsup.c new file mode 100644 index 00000000..8eecacef --- /dev/null +++ b/CASA-auth-token/native/client/mechanisms/pwd/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_PW_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/native/client/mechanisms/pwd/windows/platform.c b/CASA-auth-token/native/client/mechanisms/pwd/windows/platform.c new file mode 100644 index 00000000..869b581c --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/mechanisms/pwd/windows/platform.h b/CASA-auth-token/native/client/mechanisms/pwd/windows/platform.h new file mode 100644 index 00000000..ece8baa3 --- /dev/null +++ b/CASA-auth-token/native/client/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, "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/native/client/mechanisms/pwd/windows/pwmech.def b/CASA-auth-token/native/client/mechanisms/pwd/windows/pwmech.def new file mode 100644 index 00000000..0557e401 --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/test/CASA_Auth.cpp b/CASA-auth-token/native/client/test/CASA_Auth.cpp new file mode 100644 index 00000000..378da8ef --- /dev/null +++ b/CASA-auth-token/native/client/test/CASA_Auth.cpp @@ -0,0 +1,513 @@ +/*********************************************************************** + * + * 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 "casa_c_authtoken.h" + +// Globals +char usageString[] = "usage: test -a serverAddress -p serverPort [-h]\n"; + +char *pServerAddress = NULL; +int serverPort = 0; +BOOLEAN execHttpTest = FALSE; + + +/*********************************************************************** + * + * 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; +} + + +/*********************************************************************** + * + * 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[4096]; + int authTokenLen = sizeof(authToken); + + // Obtain an authentication token for the testService + retStatus = ObtainAuthToken("testService", 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; + int winsockStartupResult; + WSADATA winsockData; + + printf("-NonHttpTest- ObtainAuthToken succedded, tokenlen = %d\n", authTokenLen); + + // Send the token to the server + // + // First initialize winsock + if ((winsockStartupResult = WSAStartup(MAKEWORD(2,2), &winsockData)) == 0) + { + // 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", WSAGetLastError()); + } + 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); + } + + // Close winsock + WSACleanup(); + } + else + { + printf("-NonHttpTest- WSAStartup failed, error = %d\n", winsockStartupResult); + } + } +} + + +/*********************************************************************** + * + * HttpTest() + * + ***********************************************************************/ +void HttpTest(void) +{ + CasaStatus retStatus; + char authToken[4096]; + int authTokenLen = sizeof(authToken); + + // Obtain an authentication token for the testService + retStatus = ObtainAuthToken("testService", 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; + int winsockStartupResult; + WSADATA winsockData; + + //printf("ObtainAuthToken succedded, token = %s\n", authToken); + printf("-HttpTest- ObtainAuthToken succedded, tokenlen = %d\n", authTokenLen); + + // Send the token to the server + // + // First initialize winsock + if ((winsockStartupResult = WSAStartup(MAKEWORD(2,2), &winsockData)) == 0) + { + // 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", WSAGetLastError()); + } + 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) + { + char *pEncodedCredentials; + + memcpy(pBasicCredentials, CasaPrincipal, sizeof(CasaPrincipal)); + strcat(pBasicCredentials, authToken); + + // Now Base64 encode the credentials + if (EncodeData(pBasicCredentials, strlen(pBasicCredentials), &pEncodedBasicCredentials, &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); + } + + // Close winsock + WSACleanup(); + } + else + { + printf("-HttpTest- WSAStartup failed, error = %d\n", winsockStartupResult); + } + } +} + + +/*********************************************************************** + * + * 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], strlen(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) + { + // 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/native/client/test/test.vcproj b/CASA-auth-token/native/client/test/test.vcproj new file mode 100644 index 00000000..f513e4f0 --- /dev/null +++ b/CASA-auth-token/native/client/test/test.vcproj @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CASA-auth-token/native/client/util.c b/CASA-auth-token/native/client/util.c new file mode 100644 index 00000000..b93a5508 --- /dev/null +++ b/CASA-auth-token/native/client/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/native/client/windows/authtoken.def b/CASA-auth-token/native/client/windows/authtoken.def new file mode 100644 index 00000000..1862e07e --- /dev/null +++ b/CASA-auth-token/native/client/windows/authtoken.def @@ -0,0 +1,10 @@ +LIBRARY AUTHTOKEN +DESCRIPTION 'CASA Authentication Token Library.' + + +EXPORTS +; DllRegisterServer PRIVATE +; DllUnregisterServer PRIVATE +; DllGetClassObject PRIVATE + ObtainAuthToken PRIVATE +; DllCanUnloadNow PRIVATE \ No newline at end of file diff --git a/CASA-auth-token/native/client/windows/cache.c b/CASA-auth-token/native/client/windows/cache.c new file mode 100644 index 00000000..8405550a --- /dev/null +++ b/CASA-auth-token/native/client/windows/cache.c @@ -0,0 +1,1091 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Registry Key/Value defines used in the AuthCache +// +#define CASA_AUTH_CACHE_REG_KEY "CASA_Auth_Cache" +#define CREATION_TIME_REG_VALUE "CreationTime" +#define EXPIRATION_TIME_REG_VALUE "ExpirationTime" +#define DOES_NOT_EXPIRE_REG_VALUE "DoesNotExpire" +#define STATUS_REG_VALUE "Status" +#define TOKEN_REG_VALUE "Token" + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// In memory auth cache list head +static +LIST_ENTRY g_authCacheListHead; + +// Non-host specific key name +static +char g_allHosts[] = "AllHosts"; + +static +int g_cacheEntryCount = 0; + +//++======================================================================= +static +AuthCacheEntry* +CreateAuthCacheEntry( + IN const char *pCacheKeyName, + IN const char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + AuthCacheEntry *pEntry; + + DbgTrace(1, "-CreateAuthCacheEntry- Start\n", 0); + + // Use allHosts if a host name was not specified + if (pHostName == NULL) + { + pHostName = g_allHosts; + } + + // Allocate space for the entry + pEntry = (AuthCacheEntry*) malloc(sizeof(*pEntry)); + if (pEntry) + { + // Zero the entry + memset(pEntry, 0, sizeof(*pEntry)); + + // Now allocate buffers to maintain copies of the CacheKeyName and host names + pEntry->pCacheKeyName = (char*) malloc(strlen(pCacheKeyName) + 1); + if (pEntry->pCacheKeyName) + { + pEntry->pHostName = (char*) malloc(strlen(pHostName) + 1); + if (pEntry->pHostName) + { + // Save the names within the entry + strcpy(pEntry->pCacheKeyName, pCacheKeyName); + strcpy(pEntry->pHostName, pHostName); + + // Initialize the entries refCount + pEntry->refCount = 1; + + // Increment the cache entry count + g_cacheEntryCount ++; + } + else + { + DbgTrace(0, "-CreateAuthCacheEntry- Unable to allocate buffer for host name\n", 0); + + // Free allocated resources + free(pEntry->pCacheKeyName); + free(pEntry); + + // Adjust return parameter + pEntry = NULL; + } + } + else + { + DbgTrace(0, "-CreateAuthCacheEntry- Unable to allocate buffer for the CacheKeyName\n", 0); + + // Free allocated resources + free(pEntry); + + // Adjust return parameter + pEntry = NULL; + } + } + else + { + DbgTrace(0, "-CreateAuthCacheEntry- Unable to allocate buffer for auth cache entry\n", 0); + } + + DbgTrace(1, "-CreateAuthCacheEntry- End, pEntry = %08X\n", pEntry); + + return pEntry; +} + + +//++======================================================================= +AuthCacheEntry* +CreateSessionTokenCacheEntry( + IN const char *pCacheKey) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + return CreateAuthCacheEntry(pCacheKey, NULL); +} + + +//++======================================================================= +AuthCacheEntry* +CreateAuthTokenCacheEntry( + IN const char *pCacheKey, + IN const char *pGroupOrHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + return CreateAuthCacheEntry(pCacheKey, pGroupOrHostName); +} + + +//++======================================================================= +static +void +FreeAuthCacheEntry( + IN AuthCacheEntry *pEntry) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-FreeAuthCacheEntry- Start, pEntry = %08X\n", pEntry); + + // Free resources associated with the entry + if (pEntry->pToken) + free(pEntry->pToken); + + if (pEntry->pHostName) + free(pEntry->pHostName); + + if (pEntry->pCacheKeyName) + free(pEntry->pCacheKeyName); + + // Free the entry + free(pEntry); + + // Decrement the cache entry count + g_cacheEntryCount --; + + DbgTrace(1, "-FreeAuthCacheEntry- End\n", 0); +} + + +//++======================================================================= +void +ReleaseAuthCacheEntry( + IN AuthCacheEntry *pEntry) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-ReleaseAuthCacheEntry- Start, pEntry = %08X\n", pEntry); + + // Reduce the entries reference count and free it if it goes to zero + pEntry->refCount --; + if (pEntry->refCount == 0) + FreeAuthCacheEntry(pEntry); + + DbgTrace(1, "-ReleaseAuthCacheEntry- End\n", 0); +} + + +//++======================================================================= +void +IncAuthCacheEntryRefCount( + IN AuthCacheEntry *pEntry) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-IncAuthCacheEntryRefCount- Start, pEntry = %08X\n", pEntry); + + // Increase the entries reference count + pEntry->refCount ++; + + DbgTrace(1, "-IncAuthCacheEntryRefCount- 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; +} + + +//++======================================================================= +static +AuthCacheEntry* +FindEntryInAuthCache( + IN const char *pCacheKeyName, + IN const char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + AuthCacheEntry *pEntry = NULL; + LIST_ENTRY *pListEntry; + + DbgTrace(1, "-FindEntryInAuthCache- Start\n", 0); + + // Examine the cache, if entry found then check if it has expired + // in which case we would want to remove it from the cache. + + // Use allHosts if a host name was not specified + if (pHostName == NULL) + { + pHostName = g_allHosts; + } + + // First look through the entries in our in-memory cache + pListEntry = g_authCacheListHead.Flink; + while (pListEntry != &g_authCacheListHead) + { + AuthCacheEntry *pWrkEntry; + + // get a pointer to the entry + pWrkEntry = CONTAINING_RECORD(pListEntry, AuthCacheEntry, listEntry); + + // Check if this is an entry for the appropriate host + if (strcmp(pHostName, pWrkEntry->pHostName) == 0) + { + // This is an entry for the appropriate host, now check if it is + // also for the appropriate CacheKeyName + if (strcmp(pCacheKeyName, pWrkEntry->pCacheKeyName) == 0) + { + // This entry is for the appropriate CacheKeyName, check if it + // has not expired. + if (pWrkEntry->doesNotExpire == FALSE + && CacheEntryLifetimeExpired(pWrkEntry->creationTime, pWrkEntry->expirationTime)) + { + // The lifetime of the entry has expired, remove it from the in-memory cache + // and release it. + RemoveEntryList(&pWrkEntry->listEntry); + ReleaseAuthCacheEntry(pWrkEntry); + } + else + { + // This cache entry is still good, use it. + pEntry = pWrkEntry; + } + + // No need to keep looking in the in-memory cache + break; + + } + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Look in the persistent cache if an entry was not found in the in-memory cache + if (pEntry == NULL) + { + LONG status; + HKEY hCASARegKey; + + // Open CASA Auth Cache Key + status = RegOpenKeyExA(HKEY_CURRENT_USER, + CASA_AUTH_CACHE_REG_KEY, + 0, + KEY_ALL_ACCESS, + &hCASARegKey); + if (status == ERROR_SUCCESS) + { + HKEY hHostRegKey; + + // CASA Auth Cache key opened, now try to open + // key for the host. + status = RegOpenKeyExA(hCASARegKey, + pHostName, + 0, + KEY_ALL_ACCESS, + &hHostRegKey); + if (status == ERROR_SUCCESS) + { + HKEY hCacheKeyNameRegKey; + + // Host key opened, now try to open key + // for the CacheKeyName. + status = RegOpenKeyExA(hHostRegKey, + pCacheKeyName, + 0, + KEY_ALL_ACCESS, + &hCacheKeyNameRegKey); + if (status == ERROR_SUCCESS) + { + DWORD creationTime; + DWORD expirationTime; + BOOL doesNotExpire; + BOOL deleteCacheKeyNameKey = TRUE; + DWORD variableSz; + + // Key for the CacheKeyName key opened, now determine whether + // or not its lifetime has expired. + // + // Read the creation time value + variableSz = sizeof(creationTime); + status = RegQueryValueExA(hCacheKeyNameRegKey, + CREATION_TIME_REG_VALUE, + NULL, + NULL, + (LPBYTE) &creationTime, + &variableSz); + if (status == ERROR_SUCCESS) + { + // Read the expiration time + variableSz = sizeof(expirationTime); + status = RegQueryValueExA(hCacheKeyNameRegKey, + EXPIRATION_TIME_REG_VALUE, + NULL, + NULL, + (LPBYTE) &expirationTime, + &variableSz); + if (status == ERROR_SUCCESS) + { + // Read the does not expire + variableSz = sizeof(doesNotExpire); + status = RegQueryValueExA(hCacheKeyNameRegKey, + EXPIRATION_TIME_REG_VALUE, + NULL, + NULL, + (LPBYTE) &doesNotExpire, + &variableSz); + if (status == ERROR_SUCCESS) + { + // Check if the extry lifetime has been exceeded + if (doesNotExpire == TRUE + || CacheEntryLifetimeExpired(creationTime, expirationTime) == FALSE) + { + // Create a AuthCacheEntry + pEntry = CreateAuthCacheEntry(pCacheKeyName, pHostName); + if (pEntry) + { + BOOL entryInitialized = FALSE; + + // Start setting up the AuthCacheEntry + pEntry->creationTime = creationTime; + pEntry->expirationTime = expirationTime; + pEntry->doesNotExpire = doesNotExpire; + + // Read the status + variableSz = sizeof(pEntry->status); + status = RegQueryValueExA(hCacheKeyNameRegKey, + STATUS_REG_VALUE, + NULL, + NULL, + (LPBYTE) &pEntry->status, + &variableSz); + if (status == ERROR_SUCCESS) + { + // Check if there is also an auth token associated with + // this entry. + if (pEntry->status == CASA_STATUS_SUCCESS) + { + DWORD tokenSz = 0; + + // There should be an auth token associated with this CacheKeyName, + // first determine what size buffer to allocate for it. + status = RegQueryValueExA(hCacheKeyNameRegKey, + TOKEN_REG_VALUE, + NULL, + NULL, + (LPBYTE) pEntry->pToken, + &tokenSz); + if (status == ERROR_SUCCESS + || status == ERROR_MORE_DATA) + { + // Allocate buffer to hold the auth token + pEntry->pToken = (char*) malloc(tokenSz); + if (pEntry->pToken) + { + // Now read token into the allocated buffer + status = RegQueryValueExA(hCacheKeyNameRegKey, + TOKEN_REG_VALUE, + NULL, + NULL, + (LPBYTE) pEntry->pToken, + &tokenSz); + if (status == ERROR_SUCCESS) + { + // The cache entry has been properly initialized, + // add it to the in-memory cache. + entryInitialized = TRUE; + deleteCacheKeyNameKey = FALSE; + InsertHeadList(&g_authCacheListHead, &pEntry->listEntry); + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading token, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Unable to allocate buffer for token\n", 0); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading token2, status = %d\n", status); + } + } + else + { + // There is no auth token associated with this entry + // + // The cache entry has been properly initialized, + // add it to the in-memory cache. + entryInitialized = TRUE; + deleteCacheKeyNameKey = FALSE; + InsertHeadList(&g_authCacheListHead, &pEntry->listEntry); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading status, status = %d\n", status); + } + + // Free the auth cache entry if it was not successfully initialized + if (entryInitialized == FALSE) + { + FreeAuthCacheEntry(pEntry); + pEntry = NULL; + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error creating auth cache entry\n", 0); + } + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading does not expire, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading expiration time, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading creation time, status = %d\n", status); + } + + // Close CacheKeyName key + RegCloseKey(hCacheKeyNameRegKey); + + // Delete the CacheKeyName key if necessary + if (deleteCacheKeyNameKey) + { + RegDeleteKey(hHostRegKey, pCacheKeyName); + } + } + + // Close host key + RegCloseKey(hHostRegKey); + } + + // Close CASA_Auth_Cache key + RegCloseKey(hCASARegKey); + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error opening CASA Auth Cache key, status = %d\n", status); + } + } + + // Increment the reference count of entry being returned + if (pEntry) + { + // Increment entries reference count since we are returning it to the caller + IncAuthCacheEntryRefCount(pEntry); + } + + DbgTrace(1, "-FindEntryInAuthCache- End, pEntry = %08X\n", pEntry); + + return pEntry; +} + + +//++======================================================================= +AuthCacheEntry* +FindSessionTokenEntryInCache( + IN const char *pCacheKey) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + return FindEntryInAuthCache(pCacheKey, NULL); +} + +//++======================================================================= +AuthCacheEntry* +FindAuthTokenEntryInCache( + IN const char *pCacheKey, + IN const char *pGroupOrHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + return FindEntryInAuthCache(pCacheKey, pGroupOrHostName); +} + + +//++======================================================================= +void +AddEntryToAuthCache( + IN AuthCacheEntry *pEntry, + IN int entryLifetime) // seconds (0 == Lives forever) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + LONG status; + HKEY hCASARegKey; + + DbgTrace(1, "-AddEntryToAuthCache- Start, pEntry = %08X\n", pEntry); + + // 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; + } + + // Save the entry in our persistent cache (registry) + // + // Open CASA Auth Cache key + status = RegOpenKeyExA(HKEY_CURRENT_USER, + CASA_AUTH_CACHE_REG_KEY, + 0, + KEY_ALL_ACCESS, + &hCASARegKey); + if (status == ERROR_SUCCESS) + { + HKEY hHostRegKey; + + // CASA_Auth_Cache key created or opened, now open or create key for the host. + status = RegCreateKeyExA(hCASARegKey, + pEntry->pHostName, + 0, + NULL, + REG_OPTION_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hHostRegKey, + NULL); + if (status == ERROR_SUCCESS) + { + HKEY hCacheKeyNameRegKey; + + // Host key created or opened, now create key for the CacheKeyName. + status = RegCreateKeyExA(hHostRegKey, + pEntry->pCacheKeyName, + 0, + NULL, + REG_OPTION_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hCacheKeyNameRegKey, + NULL); + if (status == ERROR_SUCCESS) + { + // Write entry values + status = RegSetValueExA(hCacheKeyNameRegKey, + CREATION_TIME_REG_VALUE, + 0, + REG_DWORD, + (LPBYTE) &pEntry->creationTime, + sizeof(pEntry->creationTime)); + if (status == ERROR_SUCCESS) + { + status = RegSetValueExA(hCacheKeyNameRegKey, + EXPIRATION_TIME_REG_VALUE, + 0, + REG_DWORD, + (LPBYTE) &pEntry->expirationTime, + sizeof(pEntry->expirationTime)); + if (status == ERROR_SUCCESS) + { + status = RegSetValueExA(hCacheKeyNameRegKey, + DOES_NOT_EXPIRE_REG_VALUE, + 0, + REG_DWORD, + (LPBYTE) &pEntry->doesNotExpire, + sizeof(pEntry->doesNotExpire)); + if (status == ERROR_SUCCESS) + { + status = RegSetValueExA(hCacheKeyNameRegKey, + STATUS_REG_VALUE, + 0, + REG_DWORD, + (LPBYTE) &pEntry->status, + sizeof(pEntry->status)); + if (status == ERROR_SUCCESS) + { + // Check if there is also an auth token associated with this entry + // this entry. + if (pEntry->status == CASA_STATUS_SUCCESS) + { + status = RegSetValueExA(hCacheKeyNameRegKey, + TOKEN_REG_VALUE, + 0, + REG_SZ, + (LPBYTE) pEntry->pToken, + (DWORD) strlen(pEntry->pToken) + 1); + if (status != ERROR_SUCCESS) + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting token, status = %d\n", status); + } + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting status, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting does not expire, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting expiration time, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting creation time, status = %d\n", status); + } + + // Close CacheKeyName key + RegCloseKey(hCacheKeyNameRegKey); + + // Delete the CacheKeyName key if not successful + if (status != ERROR_SUCCESS) + { + RegDeleteKey(hHostRegKey, pEntry->pCacheKeyName); + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error creating key for CacheKeyName, status = %d\n", status); + } + + // Close host key + RegCloseKey(hHostRegKey); + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error creating key for host, status = %d\n", status); + } + + // Close CASA_Auth_Cache key + RegCloseKey(hCASARegKey); + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error opening CASA Auth Cache Key, status = %d\n", status); + } + + // Either place the cache entry in our in-memory cache or + // free it depending on the status of the operations performed. + if (status == ERROR_SUCCESS) + { + // The entry was added to the cache, save it in + // our in-memory cache. + InsertHeadList(&g_authCacheListHead, &pEntry->listEntry); + + // Increment its reference count since we are keeping a reference + IncAuthCacheEntryRefCount(pEntry); + } + + DbgTrace(1, "-AddEntryToAuthCache- End\n", 0); +} + + +//++======================================================================= +CasaStatus +InitializeAuthCache(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + PSID pEveryoneSID; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + + DbgTrace(1, "-InitializeAuthCache- Start\n", 0); + + // Initialize the cache list head + InitializeListHead(&g_authCacheListHead); + + // Lets create the CASA Auth Cache registry key in the + // user's hive and limit access to it. + // + // Create a well-known SID for the Everyone group. + if (AllocateAndInitializeSid(&SIDAuthWorld, + 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &pEveryoneSID)) + { + EXPLICIT_ACCESS ea[3] = {0}; + SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; + PSID pAdminSID; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will revoke Everyone access to the key. + ea[0].grfAccessPermissions = KEY_ALL_ACCESS; + ea[0].grfAccessMode = REVOKE_ACCESS; + ea[0].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; + ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID; + + // Create a SID for the BUILTIN\Administrators group. + if (AllocateAndInitializeSid(&SIDAuthNT, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &pAdminSID)) + { + DWORD status; + PACL pACL; + HANDLE hToken; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will revoke the Administrators group access to the key. + ea[1].grfAccessPermissions = KEY_ALL_ACCESS; + ea[1].grfAccessMode = REVOKE_ACCESS; + ea[1].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; + ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID; + + // Create a SID for the interactive user, first get the process token + if (OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY, + &hToken)) + { + char tokenInformation[1024]; + DWORD infoLength; + + if (GetTokenInformation(hToken, + TokenUser, + tokenInformation, + sizeof(tokenInformation), + &infoLength)) + { + TOKEN_USER *pTokenUser = (TOKEN_USER*) tokenInformation; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will grant the interactive user access to the key. + ea[2].grfAccessPermissions = KEY_ALL_ACCESS; + ea[2].grfAccessMode = SET_ACCESS; + ea[2].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; + ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[2].Trustee.TrusteeType = TRUSTEE_IS_USER; + ea[2].Trustee.ptstrName = (LPTSTR) pTokenUser->User.Sid; + + // Create a new ACL that contains the new ACEs. + status = SetEntriesInAcl(3, ea, NULL, &pACL); + if (status == ERROR_SUCCESS) + { + PSECURITY_DESCRIPTOR pSD; + + // Allocate space for a security descriptor + pSD = (SECURITY_DESCRIPTOR*) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (pSD) + { + // Initialize a security descriptor + if (InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) + { + // Add the ACL to the security descriptor + if (SetSecurityDescriptorDacl(pSD, + TRUE, // bDaclPresent flag + pACL, + FALSE)) // not a default DACL + { + SECURITY_ATTRIBUTES sa; + HKEY hCASARegKey; + DWORD disposition; + + // Initialize a security attributes structure + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + + // Now create the CASA Auth Cache registry key for this user + // with the required access control restrictions. + status = RegCreateKeyExA(HKEY_CURRENT_USER, + CASA_AUTH_CACHE_REG_KEY, + 0, + NULL, + REG_OPTION_VOLATILE, + KEY_ALL_ACCESS, + &sa, + &hCASARegKey, + &disposition); + if (status == ERROR_SUCCESS) + { + // Success + retStatus = CASA_STATUS_SUCCESS; + + // Close CASA_Auth_Cache key + RegCloseKey(hCASARegKey); + } + else + { + DbgTrace(0, "-InitializeAuthCache- Error creating CASA Key, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-InitializeAuthCache- SetSecurityDescriptorDacl Error = %d\n", GetLastError()); + } + } + else + { + DbgTrace(0, "-InitializeAuthCache- InitializeSecurityDescriptor Error %d\n", GetLastError()); + } + + // Free the space allocated for the security descriptor + LocalFree(pSD); + } + else + { + DbgTrace(0, "-InitializeAuthCache- Unable to allocate memory for SD\n", 0); + } + + // Free the ACL structure + LocalFree(pACL); + } + else + { + DbgTrace(0, "-InitializeAuthCache- SetEntriesInAcl Error %d\n", status); + } + } + else + { + DbgTrace(0, "-InitializeAuthCache- Error obtaining token information, error = %d\n", GetLastError()); + } + + // Release the process token handle + CloseHandle(hToken); + } + else + { + DbgTrace(0, "-InitializeAuthCache- Unable to obtain process token, error = %d\n", GetLastError()); + } + + // Free the SID for the administrator + FreeSid(pAdminSID); + } + else + { + DbgTrace(0, "-InitializeAuthCache- AllocateAndInitializeSid Error %d\n", GetLastError()); + } + + // Free the SID for everyone + FreeSid(pEveryoneSID); + } + else + { + DbgTrace(0, "-InitializeAuthCache- AllocateAndInitializeSid Error = %d\n", GetLastError()); + } + + DbgTrace(1, "-InitializeAuthCache- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/client/windows/dllsup.c b/CASA-auth-token/native/client/windows/dllsup.c new file mode 100644 index 00000000..f6d3da15 --- /dev/null +++ b/CASA-auth-token/native/client/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("CASAAUTH -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/native/client/windows/platform.c b/CASA-auth-token/native/client/windows/platform.c new file mode 100644 index 00000000..e359d8eb --- /dev/null +++ b/CASA-auth-token/native/client/windows/platform.c @@ -0,0 +1,549 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// Global synchronization mutex for the user +static +HANDLE hUserMutex; + +// Normalized host name cache list head +static +LIST_ENTRY normalizedHostNameCacheListHead; + +// Synchronization mutex for the normalized host name cache +static +HANDLE hNormalizedHostNameCacheMutex; + +// Authentication mechanism configuration file folder +char mechConfigFolder[] = "\\Program Files\\Novell\\Casa\\Etc\\Auth\\Mechanisms"; + +// Path separator +char pathCharString[] = "\\"; + + +//++======================================================================= +CasaStatus +CreateUserMutex(void) +// +// 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) + { + hUserMutex = CreateMutex(&mutexAttributes, + FALSE, + mutexName); + if (hUserMutex == NULL) + { + DbgTrace(0, "-CreateUserMutex- CreteMutex 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- Un-expected 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(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-AcquireUserMutex- Start\n", 0); + + WaitForSingleObject(hUserMutex, INFINITE); + + DbgTrace(2, "-AcquireUserMutex- End\n", 0); +} + + +//++======================================================================= +void +ReleaseUserMutex(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(2, "-ReleaseUserMutex- Start\n", 0); + + if (ReleaseMutex(hUserMutex) == 0) + { + DbgTrace(0, "-ReleaseUserMutex- ReleaseMutex failed, error = %d\n", GetLastError()); + } + + DbgTrace(2, "-ReleaseUserMutex- 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/native/client/windows/platform.h b/CASA-auth-token/native/client/windows/platform.h new file mode 100644 index 00000000..b1729a01 --- /dev/null +++ b/CASA-auth-token/native/client/windows/platform.h @@ -0,0 +1,114 @@ +/*********************************************************************** + * + * 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("AuthToken %s", printBuff); \ +// } \ +//} +#define DbgTrace(LEVEL, X, Y) { \ +char formatBuff[128]; \ +char printBuff[256]; \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + strcpy(formatBuff, "AuthToken "); \ + strncat(formatBuff, X, sizeof(formatBuff) - 10); \ + _snprintf(printBuff, sizeof(printBuff), formatBuff, Y); \ + OutputDebugString(printBuff); \ + } \ +} + + +#define bool BOOLEAN +#define true TRUE +#define false FALSE + +// +// Auth Cache Entry definition +// +typedef struct _AuthCacheEntry +{ + LIST_ENTRY listEntry; + int refCount; + DWORD creationTime; + DWORD expirationTime; + BOOL doesNotExpire; + char *pHostName; + char *pCacheKeyName; + char *pToken; + int status; + +} AuthCacheEntry, *PAuthCacheEntry; + +// +// Rpc Session definition +// +typedef struct _RpcSession +{ + HINTERNET hSession; + HINTERNET hConnection; + +} RpcSession, *PRpcSession; + +// +// Other definitions +// +#define LIB_HANDLE HMODULE + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + +//========================================================================= + diff --git a/CASA-auth-token/native/client/windows/rpc.c b/CASA-auth-token/native/client/windows/rpc.c new file mode 100644 index 00000000..96b4716f --- /dev/null +++ b/CASA-auth-token/native/client/windows/rpc.c @@ -0,0 +1,498 @@ +/*********************************************************************** + * + * 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; +} + + +//++======================================================================= +RpcSession* +OpenRpcSession( + IN char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + RpcSession *pSession; + + + 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)); + + // 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, + 8080, /*INTERNET_DEFAULT_HTTP_PORT,*/ + 0); + if (pSession->hConnection == NULL) + { + DbgTrace(0, "-OpenRpcSession- Failed to open connection, error = %d\n", GetLastError()); + + // Free allocated resources + WinHttpCloseHandle(pSession->hSession); + free(pSession); + pSession = NULL; + } + + // Free the host name wide string buffer + free(pWideHostName); + } + else + { + DbgTrace(0, "-OpenRpcSession- Error converting host name to wide string\n", 0); + + // Free allocated resources + WinHttpCloseHandle(pSession->hSession); + free(pSession); + pSession = NULL; + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to open session, error = %d\n", GetLastError()); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for rpc session\n", 0); + } + + 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 the space allocated for the session + free(pSession); + + DbgTrace(1, "-CloseRpcSession- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +InternalRpc( + IN RpcSession *pSession, + IN char *pMethod, + IN bool secure, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + char rpcTarget[256]; + LPWSTR pWideRpcTarget; + int wideRpcTargetLen; + WCHAR sendHeaders[] = L"Content-Type: text/html"; + + 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; + + // Open a request handle + hRequest = WinHttpOpenRequest(pSession->hConnection, + L"POST", + pWideRpcTarget, + NULL, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + secure? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH); + if (hRequest) + { + int reqDataLen = (int) strlen(pRequestData); + + // Send the request + if (WinHttpSendRequest(hRequest, + sendHeaders, + -1, + pRequestData, + reqDataLen, + reqDataLen, + 0)) + { + // 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(); + + DbgTrace(0, "-InternalRpc- Unsuccessful send http request, error = %d\n", error); + if (error == ERROR_WINHTTP_CANNOT_CONNECT) + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_AUTH_SERVER_UNAVAILABLE); + } + else + { + 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); + } + + // 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 bool secure, + 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, + secure, + 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; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/configure.in b/CASA-auth-token/native/configure.in new file mode 100644 index 00000000..cea08657 --- /dev/null +++ b/CASA-auth-token/native/configure.in @@ -0,0 +1,279 @@ +####################################################################### +# +# 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(include/casa_s_authtoken.h) +AC_CANONICAL_SYSTEM +AM_INIT_AUTOMAKE(CASA_auth_token_native, 0.1.1) +RELEASE=`date +%Y%m%d_%H%M` +AC_SUBST(RELEASE) +AM_MAINTAINER_MODE + +# +# Check for a valid C# compiler +# +#AC_CHECK_PROG(CSC, csc, csc) +#test -z "$CSC" && AC_CHECK_PROG(CSC, mcs, mcs) +#test -z "$CSC" && AC_MSG_ERROR([no acceptable C Sharp compiler found in \$PATH]) + +# +# Check for valid C# compiler in linux +# +case $host_os in + cygwin*) + ;; + *) + AC_CHECK_PROG(CSC, csc, csc) + test -z "$CSC" && AC_CHECK_PROG(CSC, mcs, mcs) + test -z "$CSC" && AC_MSG_ERROR([no acceptable C Sharp compiler found in \$PATH]) + + ;; +esac + +case $CSC in + # + # Mono-specific configuration + # + mcs) + CSC_EXEFLAG=/target:exe + CSC_LIBFLAG=/target:library + CSC_EXEFLAG=/target:exe + CSC_WINEXEFLAG=/target:winexe + CSCFLAGS='/d:MONO /warn:4 /d:TRACE -d:LINUX' + CSCFLAGS_DEBUG="/debug+ /d:DEBUG" + CSCFLAGS_OPTIMIZE="/optimize+" + MONO=mono + MONO_DEBUG='mono --debug' + MONO_PATH= + SYSTEM_XML='System.Xml.dll' + ;; + # + # .NET-specific configuration + # + csc) + CSC_EXEFLAG=/target:exe + CSC_LIBFLAG=/target:library + CSC_EXEFLAG=/target:exe + CSC_WINEXEFLAG=/target:winexe + CSCFLAGS='/d:DOTNET /warn:4 /d:TRACE /nologo' + CSCFLAGS_DEBUG="/debug+ /d:DEBUG" + CSCFLAGS_OPTIMIZE="/optimize+" + MONO= + MONO_DEBUG= + MONO_PATH= + SYSTEM_XML='System.XML.dll' + ;; +esac + +AC_SUBST(CSC) +AC_SUBST(CSC_EXEFLAG) +AC_SUBST(CSC_LIBFLAG) +AC_SUBST(CSC_WINEXEFLAG) +AC_SUBST(CSCFLAGS) +AC_SUBST(CSCFLAGS_DEBUG) +AC_SUBST(MONO) +AC_SUBST(MONO_PATH) +AC_SUBST(SYSTEM_XML) + +SRCDIR='$(top_srcdir)' +DOCDIR="$SRCDIR/doc" +TOOLDIR='$(top_srcdir)/tools' +AC_SUBST(SRCDIR) +AC_SUBST(DOCDIR) +AC_SUBST(TOOLDIR) +EMPTY= +SPACE='$(EMPTY) $(EMPTY)' + +AC_SUBST(EMPTY) +AC_SUBST(SPACE) + +# +# Check for operating system and set TARGET_OS +# +case $host_os in + cygwin*) + TARGET_OS='windows' + ;; + *) + TARGET_OS='linux' + ;; +esac + +AC_SUBST(TARGET_OS) +AM_CONDITIONAL(LINUX, test "$TARGET_OS" = "linux") +AM_CONDITIONAL(WINDOWS, test "$TARGET_OS" = "windows") + +# +# Check for architecture and set TARGET_ARCH +# ia64 needs to be treated as non64. + +case $target_cpu in + x86_64|p*pc64|s390x) + LIB=lib64 + ;; + *ia64|*) + LIB=lib + ;; +esac + +AC_SUBST(LIB) +AM_CONDITIONAL(LIB64, test "$LIB" = lib64) + +# +# +# Set platform-specific variables +# +case $TARGET_OS in + # + # Linux-specific configuration + # + linux) + # + # Set variables + # + COMMON_CLEAN_FILES='' + ICON_EXT='.ico' + ICON_FLAG='/resource:' + PLATFORM_SUBDIRS=$LINUX_SUBDIRS + SEP='/' + LINK=gcc + ;; + # + # Windows-specific configuration + # + windows) + COMMON_CLEAN_FILES='*.suo */*.suo *.csproj.user */*.csproj.user bin obj */bin */obj *.xml */*.xml *.pdb */*.pdb' + ICON_EXT='.ico' + ICON_FLAG='/win32icon:' + PLATFORM_SUBDIRS=$WINDOWS_SUBDIRS + SEP='$(EMPTY)\\$(EMPTY)' + LINK=link.exe + ;; +esac +AC_SUBST(COMMON_CLEAN_FILES) +AC_SUBST(ICON_EXT) +AC_SUBST(ICON_FLAG) +AC_SUBST(PLATFORM_SUBDIRS) +AC_SUBST(SEP) +AC_SUBST(LINK) + +# +# Run standard macros +# +AM_PROG_CC_STDC +AC_PROG_INSTALL +AC_HEADER_STDC + +####### +# +# set CFLAGS +# +case $host_os in + linux*) + CFLAGS="$CFLAGS" + ;; + cygwin*) + CC=cl.exe + CFLAGS="-D WIN32 -D SSCS_WIN32_PLAT_F -D N_PLAT_CLIENT -MT -Ox" + ;; +esac + +# +# Handle --enable-debug +# +AC_ARG_ENABLE(debug, [ + --enable-debug configure the Makefiles to build in DEBUG mode], + [case "${enableval}" in + yes) enable_debug=true ;; + no) enable_debug=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; + esac],[enable_debug=false]) +AM_CONDITIONAL(DEBUG, test x$enable_debug = xtrue) +if test "$enable_debug" = "true" +then + # Build debug version. + # CFLAGS="$CFLAGS_DEBUG $CFLAGS -DDBG -DDEBUG" + CFLAGS="$CFLAGS_DEBUG $CFLAGS -g -DDBG -DDEBUG \ +-fPIC -DPIC -DSSCS_LINUX_PLAT_F -O2 -fmessage-length=0 -Wall \ +-D_REENTRANT -DALIGNMENT -DN_PLAT_UNIX \ +-DUNIX -DLINUX -DIAPX38" + CSCFLAGS="$CSCFLAGS_DEBUG $CSCFLAGS" + CXXFLAGS="$CXXFLAGS_DEBUG $CXXFLAGS" + DEVENV_CONFIGURATION=Debug + MONO=$MONO_DEBUG +else + # Build optimized version. + CFLAGS="$CFLAGS_OPTIMIZE $CFLAGS -g -fPIC -DPIC \ +-DSSCS_LINUX_PLAT_F -O2 -fmessage-length=0 -Wall \ +-D_REENTRANT -DALIGNMENT -DN_PLAT_UNIX \ +-DUNIX -DLINUX -DIAPX38" + CSCFLAGS="$CSCFLAGS_OPTIMIZE $CSCFLAGS" + CXXFLAGS="$CXXFLAGS_OPTIMIZE $CXXFLAGS" + DEVENV_CONFIGURATION=Release +fi +AC_SUBST(CSCFLAGS) +AC_SUBST(DEVENV_CONFIGURATION) + +##comment out due to build failure +# Check for GCC version to add fstack-protector flag +# +#GCC_VER="`gcc -dumpversion`" +#case "$GCC_VER" in +# 3*) +# ;; +# 4*) +# CFLAGS="$CFLAGS -fstack-protector" +# ;; +# *) +# ;; +#esac + +AC_SUBST(GCC_VER) + +# +# Configure PKG_CONFIG +# +AC_PATH_PROG(PKG_CONFIG, pkg-config, no) +if test "x$PKG_CONFIG" = "xno"; then + AC_MSG_ERROR([You need to install pkg-config]) +fi + +# +# Configure files +# +AC_OUTPUT([ +Makefile +package/Makefile +package/linux/Makefile +package/linux/CASA_auth_token_native.spec +include/Makefile +server/Makefile +server/AuthTokenValidate/Makefile +server/AuthTokenValidate/linux/Makefile +server/AuthTokenValidate/idenTokenProviders/Makefile +server/AuthTokenValidate/idenTokenProviders/casa/Makefile +server/AuthTokenValidate/idenTokenProviders/casa/linux/Makefile +server/PamSupport/Makefile +server/PamSupport/linux/Makefile +server/ApacheSupport/Makefile +server/ApacheSupport/2.2/Makefile +server/ApacheSupport/2.2/linux/Makefile +]) + diff --git a/CASA-auth-token/native/include/Makefile.am b/CASA-auth-token/native/include/Makefile.am new file mode 100644 index 00000000..f506f2fe --- /dev/null +++ b/CASA-auth-token/native/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/native/include/casa_c_authtoken.h b/CASA-auth-token/native/include/casa_c_authtoken.h new file mode 100644 index 00000000..4dd91ad3 --- /dev/null +++ b/CASA-auth-token/native/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/native/include/casa_s_authtoken.h b/CASA-auth-token/native/include/casa_s_authtoken.h new file mode 100644 index 00000000..b0d29954 --- /dev/null +++ b/CASA-auth-token/native/include/casa_s_authtoken.h @@ -0,0 +1,305 @@ +/*********************************************************************** + * + * 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_S_AUTHTOKEN_H_ +#define _CASA_S_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 ]================================================== + + +/************************************************************************** +*************************************************************************** +** ** +** Principal Interface Definition ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +typedef +int +(SSCS_CALL *PFNPrincipalIf_AddReference)( + IN const void *pIfInstance); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +//=======================================================================-- + + +//++======================================================================= +typedef +void +(SSCS_CALL *PFNPrincipalIf_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 *PFNPrincipalIf_GetIdentityId)( + IN const void *pIfInstance, + INOUT char *pIdentIdBuf, + INOUT int *pIdentIdLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pIdentIdBuf - +// Pointer to buffer that will receive the identity id. The returned +// id will be in the form of a NULL terminated string. +// +// pIdentIdBufLen - +// Pointer to variable with the length of the buffer pointed by +// pIdentIdBuf. On exit it contains the length of the returned id +// (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the identity id associated with the identity token. +//=======================================================================-- + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFNPrincipalIf_GetSourceName)( + IN const void *pIfInstance, + INOUT char *pSourceNameBuf, + INOUT int *pSourceNameLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pSourceNameBuf - +// Pointer to buffer that will receive the name associated with the +// identity information source. The returned name will be in the form +// of a NULL terminated string. +// +// pSourceNameBufLen - +// Pointer to variable with the length of the buffer pointed by +// pSourceNameBuf. On exit it contains the length of the returned +// name (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the name of the identity source associated with the identity token. +//=======================================================================-- + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFNPrincipalIf_GetSourceUrl)( + IN const void *pIfInstance, + INOUT char *pSourceUrlBuf, + INOUT int *pSourceUrlLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pSourceUrlBuf - +// Pointer to buffer that will receive the URL associated with the +// identity information source. The returned URL will be in the form +// of a NULL terminated string. +// +// pSourceUrlBufLen - +// Pointer to variable with the length of the buffer pointed by +// pSourceUrlBuf. On exit it contains the length of the returned +// URL (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the URL to the identity source associated with the identity token. +//=======================================================================-- + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFNPrincipalIf_AttributeEnumerate)( + IN const void *pIfInstance, + INOUT int *pEnumHandle, + INOUT char *pAttribNameBuf, + INOUT int *pAttribNameLen, + INOUT char *pAttribValueBuf, + INOUT int *pAttribValueLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pEnumHandle - +// Pointer to enumeration handle. Must be set to 0 to start an +// enumeration. Note the enumeration handle advances if the +// function returns success. +// +// pAttribNameBuf - +// Pointer to buffer that will receive the identity attribute name. The +// returned name will be in the form of a NULL terminated string. +// +// pAttribNameLen - +// Pointer to variable with the length of the buffer pointed by +// pAttribNameBuf. On exit it contains the length of the returned +// name (including the NULL terminator). +// +// pAttribValueBuf - +// Pointer to buffer that will receive the identity attribute value. The +// returned value will be in the form of a NULL terminated string. +// +// pAttribValueLen - +// Pointer to variable with the length of the buffer pointed by +// pAttribValueBuf. On exit it contains the length of the returned +// value (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Enumerates through the attributes associated with the identity token. +//=======================================================================-- + + +// +// Principal Interface Object +// +typedef struct _PrincipalIf +{ + PFNPrincipalIf_AddReference addReference; + PFNPrincipalIf_ReleaseReference releaseReference; + PFNPrincipalIf_GetIdentityId getIdentityId; + PFNPrincipalIf_GetSourceName getSourceName; + PFNPrincipalIf_GetSourceUrl getSourceUrl; + PFNPrincipalIf_AttributeEnumerate attributeEnumerate; + +} PrincipalIf, *PPrincipalIf; + + +/************************************************************************** +*************************************************************************** +** ** +** Validate Authentication Token API ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +extern CasaStatus SSCS_CALL +ValidateAuthToken( + IN const char *pServiceName, + IN const char *pTokenBuf, + IN const int tokenBufLen, + INOUT PrincipalIf **ppPrincipalIf); +// +// Arguments: +// pServiceName - +// Pointer to NULL terminated string that contains the +// name of the service targeted by the token. +// +// 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. +// +// tokenBufLen - +// Length of the data contained within the buffer pointed +// at by pTokenBuf. +// +// ppPrincipalIf - +// Pointer to variable that will receive a pointer to a principal +// interface with information about the authenticated entity. +// IMPORTANT NOTE: The caller is responsible for releasing the +// interface after it is done with it to avoid a resource leak. +// +// Returns: +// Casa status. +// +// Description: +// Validates authentication token. +// +//=======================================================================-- + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif // #if defined(__cplusplus) || defined(c_plusplus) + +#endif // #ifndef _CASA_S_AUTHTOKEN_H_ + diff --git a/CASA-auth-token/native/include/list_entry.h b/CASA-auth-token/native/include/list_entry.h new file mode 100644 index 00000000..f482b464 --- /dev/null +++ b/CASA-auth-token/native/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/native/include/proto.h b/CASA-auth-token/native/include/proto.h new file mode 100644 index 00000000..87b90eb1 --- /dev/null +++ b/CASA-auth-token/native/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/native/package/Makefile.am b/CASA-auth-token/native/package/Makefile.am new file mode 100644 index 00000000..f6a6d745 --- /dev/null +++ b/CASA-auth-token/native/package/Makefile.am @@ -0,0 +1,38 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = linux + +DIST_SUBDIRS = linux + +EXTRA_DIST = + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +clean-local: + if [ -d lib ]; then rm -rf lib; fi + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/native/package/linux/CASA-auth-token-server-support.spec.in b/CASA-auth-token/native/package/linux/CASA-auth-token-server-support.spec.in new file mode 100644 index 00000000..79726f4b --- /dev/null +++ b/CASA-auth-token/native/package/linux/CASA-auth-token-server-support.spec.in @@ -0,0 +1,227 @@ +# +# spec file for the CASA-auth-token native packages. +# +# Copyright (c) 2006 SUSE LINUX Products GmbH, Nuernberg, Germany. +# This file and all modifications and additions to the pristine +# package are under the same license as the package itself. +# +# Please submit bugfixes or comments via http://bugs.opensuse.org +# + +# norootforbuild + +# For debug build, please replace Release to Debug and set debug_opt to --enable-debug +%define cfg Release +%define debug_opt "" + + +Name: @PACKAGE@ +URL: http://www.novell.com/products +BuildRequires: libstdc++ libgcc gcc-c++ glib2-devel krb5-devel libgssapi libstdc++-devel pam-devel pkgconfig apache2-devel update-alternatives mono-devel CASA-devel expat +%define prefix /usr +License: LGPL +Group: Applications/System +Autoreqprov: on +%define bldno 1.0.0 +Version: @VERSION@ +Release: 0 +Summary: Novell Common Authentication Services Adapter Authentication Token Infrastructure (CASA-auth-token) +Source: %{name}-%{version}.tar.bz2 +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Requires: expat +PreReq: %fillup_prereq %insserv_prereq + +%description +CASA-auth-token is an authentication token infrastructure with support for multiple +authentication mechanisms with an emphasis on providing a scalable single +sign-on solution. + +A key feature of CASA-auth-token is that its authentication tokens contain identity +information about the entity being authenticated. This information is made available +to the consuming services. The amount of information contained in the tokens is +configured on a per-service basis. Because of this feature, we say that CASA-auth-token +projects an "Authenticated Identity". + +This package contains the CASA (Common Authentication Services Adapter) +authentication token infrastructure lower level libraries for token +verification from native code ("C"). It is recomended that this library +not be invoked directly by applications, instead it is recomended that +appplication invoke its services through the support modules provided to +integrate with PAM or the Apache Web Server. + + +%package -n CASA-auth-token-pam-support +Summary: Libraries needed for PAM applications development. +Group: Applications/System +Requires: CASA-auth-token-server-support pam + +%description -n CASA-auth-token-pam-support +This package contains the CASA (Common Authentication Services Adapter) +authentication token infrastructure PAM module for token verification. + +%package -n CASA-auth-token-apache2_2-support +Summary: Libraries needed for Apache 2.2 applications development. +Group: Applications/System +Requires: apache2 CASA-auth-token-server-support + +%description -n CASA-auth-token-apache2_2-support +This package contains the CASA (Common Authentication Services Adapter) +authentication token infrastructure Apache v2.2 authentication provider +module for token verification. The module expects that users authenticate +utilizing the HTTP Basic authentication scheme and that the password utilized consist +of a CASA authentication token. Information about the authenticated identity is +made available to other Apache modules via the Apache request environment variable. + +%package -n CASA-auth-token-devel +Summary: Include files needed for applications development. +Group: Applications/System +Requires: CASA-devel CASA-auth-token-server-support CASA-auth-token-jaas-support CASA-auth-token-pam-support CASA-auth-token-apache2_2-support CASA-auth-token-service + +%description -n CASA-auth-token-devel +This package contains the files necessary for the development of client and +server applications that utilize the CASA (Common Authentication Service Adapter) +authentication token infrastructure for authentication. + + +%prep +%setup -q +#%patch +%if %{_lib} == "lib64" +%define binsource bin64 +%else +%define binsource bin +%endif + +%build +export PATH=.:$PATH:/usr/%_lib/qt3/bin +%if %suse_version > 1000 +export CFLAGS="$CFLAGS $RPM_OPT_FLAGS -fstack-protector" +%endif + +./autogen.sh +make + + +%install + +## Prime the file system ## +install -d %{buildroot}%{prefix} +install -d %{buildroot}%{prefix}/%{_lib} +install -d %{buildroot}%{prefix}/%{_lib}/security +install -d %{buildroot}%{prefix}/include + +## CASA-auth-token-server-support ## +# Libs +install -m 755 %{_lib}/%{cfg}/libcasa_s_authtoken.so %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so.%{bldno} + +# Lib Symbolic Links +ln -sf libcasa_s_authtoken.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so +ln -sf libcasa_s_authtoken.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so.1 + +## CASA-auth-token-pam-support ## +# Libs +install -m 755 %{_lib}/%{cfg}/pam_casaauthtok.so %{buildroot}%{prefix}/%{_lib}/security/pam_casaauthtok.so.%{bldno} +#install -m 755 %{_lib}/%{cfg}/pam_casaauthtok.so %{buildroot}%{prefix}/%{_lib}/security/pam_casaauthtok.so + +# Lib Symbolic Links +ln -sf pam_casaauthtok.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/security/pam_casaauthtok.so +ln -sf pam_casaauthtok.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/security/pam_casaauthtok.so.1 + +## CASA-auth-token-apache2_2-support ## +# Libs +install -m 755 %{_lib}/%{cfg}/mod_authn_casa.so %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so.%{bldno} + +# Lib Symbolic Links +ln -sf mod_authn_casa.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so +ln -sf mod_authn_casa.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so.1 + +## CASA-auth-token-devel ## +# Header Files +install -m 644 include/casa_c_authtoken.h %{buildroot}%{prefix}/include +install -m 644 include/casa_s_authtoken.h %{buildroot}%{prefix}/include + + +%clean +rm -rf $RPM_BUILD_ROOT + + +## CASA-auth-token-server-support ## +%pre +# Nothing to do in this pre script + +%post +/sbin/ldconfig + +%preun +# Nothing to do in this preun script + +%postun +# Nothing to do in this postun script + +%files +%defattr(-,root,root) +%{prefix}/%{_lib}/libcasa_s_authtoken.so.%{bldno} +%{prefix}/%{_lib}/libcasa_s_authtoken.so +%{prefix}/%{_lib}/libcasa_s_authtoken.so.1 + + +## CASA-auth-token-pam-support ## +%pre -n CASA-auth-token-pam-support +# Nothing to do in this pre script + +%post -n CASA-auth-token-pam-support +/sbin/ldconfig + +%preun -n CASA-auth-token-pam-support +# Nothing to do in this preun script + +%postun -n CASA-auth-token-pam-support +# Nothing to do in this postun script + +%files -n CASA-auth-token-pam-support +%defattr(-,root,root) +%dir %{prefix}/%{_lib}/security +%{prefix}/%{_lib}/security/pam_casaauthtok.so.%{bldno} +%{prefix}/%{_lib}/security/pam_casaauthtok.so +%{prefix}/%{_lib}/security/pam_casaauthtok.so.1 + + +## CASA-auth-token-apache2_2-support ## +%pre -n CASA-auth-token-apache2_2-support +# Nothing to do in this pre script + +%post -n CASA-auth-token-apache2_2-support +/sbin/ldconfig + +%preun -n CASA-auth-token-apache2_2-support +# Nothing to do in this preun script + +%postun -n CASA-auth-token-apache2_2-support +# Nothing to do in this postun script + +%files -n CASA-auth-token-apache2_2-support +%defattr(-,root,root) +%{prefix}/%{_lib}/mod_authn_casa.so.%{bldno} +%{prefix}/%{_lib}/mod_authn_casa.so +%{prefix}/%{_lib}/mod_authn_casa.so.1 + + +## CASA-auth-token-devel ## +%pre -n CASA-auth-token-devel +# Nothing to do in this pre script + +%post -n CASA-auth-token-devel +# Nothing to do in this post script + +%preun -n CASA-auth-token-devel +# Nothing to do in this preun script + +%postun -n CASA-auth-token-devel +# Nothing to do in this postun script + +%files -n CASA-auth-token-devel +%defattr(-,root,root) +%{prefix}/include/casa_c_authtoken.h +%{prefix}/include/casa_s_authtoken.h + +%changelog -n package diff --git a/CASA-auth-token/native/package/linux/Makefile.am b/CASA-auth-token/native/package/linux/Makefile.am new file mode 100644 index 00000000..1cace376 --- /dev/null +++ b/CASA-auth-token/native/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/native/server/ApacheSupport/2.2/Makefile.am b/CASA-auth-token/native/server/ApacheSupport/2.2/Makefile.am new file mode 100644 index 00000000..6184e626 --- /dev/null +++ b/CASA-auth-token/native/server/ApacheSupport/2.2/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 + +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/native/server/ApacheSupport/2.2/README b/CASA-auth-token/native/server/ApacheSupport/2.2/README new file mode 100644 index 00000000..39fe47da --- /dev/null +++ b/CASA-auth-token/native/server/ApacheSupport/2.2/README @@ -0,0 +1,108 @@ +/*********************************************************************** + * + * README for mod_authn_casa + * + ***********************************************************************/ + +INTRODUCTION + +mod_authn_casa is an Apache 2.2 Basic Authentication Provider that +can be configured to validate Basic Credentials carrying CASA +Authentication Tokens. + +Clients sending CASA Authentication Tokens as part of the Basic Credentials +will format them in the following manner: "username:CasaAuthenticationToken", +where the username is set to "CasaPrincipal" and the CasaAuthenticationToken +is the token string obtained from the CASA Get Authentication Token API.. + +CONFIGURATION + +To use mod_authn_casa as an authentication provider for a specific location +you must first tell Apache that it must load the module, you do this by +placing the module or a link to the module in the Apache server's modules +folder and by placing the following line in the server's httpd.conf file: + +LoadModule authn_casa_module modules/mod_authn_casa.so + +The following lines show how Apache is configured to use mod_authn_casa +for authenticating requests issued to mod_example: + + + SetHandler example-handler + AuthType Basic + AuthName "CASA-Authentication" + AuthBasicProvider casa + Require valid-user + + +Note that the name specified in the AuthName directive should match the name +configured under CASA for the authentication realm used by CASA to obtain +identity information for the service. + +mod_authn_casa supports the following configuration directives: + +UsernameCheck - This is a per-directory or per-location directive which + configures whether or not mod_authn_casa must verify that + the username is set to "CasaPrincipal". Possible values + for this directive are 'on' or 'off'. Default is 'off'. + + To enable UsernameChack for a particular location using + CASA Authentication, include the following line inside + the location configuration block: + + UsernameCheck on + +CLIENT PROGRAMMING NOTES + +HTTP Clients sending requests to a location being protected by the CASA +Authentication Provider must obtain an Authentication Token from the CASA +Client for authenticating to the Service identified as the "location" being +accessed in the HTTP Server. In the case of mod_example, the service name +would be "example-info". Once the client obtains an Authentication Token +from the CASA Client it must then include it in the HTTP Basic Authentication +header that it must include in the HTTP Request. The HTTP Basic Authentication +credentials should be in the following form: + +Base64("CasaPrincipal":"AuthenticationToken") + +SERVER PROGRAMMING NOTES + +Apache modules being protected by the CASA Authentication Provider can obtain +the following information about the authenticated identity: + +username - This is accessed via the r->user variable or by examining the IdentityId +environment variable associated with the request block. The username is the +user's unique id within the authentication realm. When the authentication realm +is an LDAP database, the username consists of the user's fdn. + +Name of the source of identity data (Authentication Realm) - This is accessed by +examining the IdentityDataSourceName environment variable associated with the +request block. + +URL to the source of identity data - This is accessed by examining the +IdentityDataSourceUrl environment variable associated with the request block. + +Attributes of the authenticated identity - The attributes are set as environment +variables associated with the request block. The environment variable names match +the names of the attributes. The attributes associated with the authenticated +identity and expressed as environment variables are configured at the time that +the service is enabled for CASA Authentication. + +Note that environment variables are contained in the r->subprocess_env table. + +SECURITY CONSIDERATIONS + +CASA Authenticatication Tokens when compromised can be used to either impersonate +a user or to obtain identity information about the user. Because of this it is +important that the tokens be secured by applications making use of them. It is +recommended that the tokens be transmitted using HTTPS. + + + + + + + + + + diff --git a/CASA-auth-token/native/server/ApacheSupport/2.2/TODO b/CASA-auth-token/native/server/ApacheSupport/2.2/TODO new file mode 100644 index 00000000..4145a4af --- /dev/null +++ b/CASA-auth-token/native/server/ApacheSupport/2.2/TODO @@ -0,0 +1,13 @@ +/*********************************************************************** + * + * TODO for mod_authn_casa + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for mod_authn_casa. + +OUTSTANDING ITEMS + +None. diff --git a/CASA-auth-token/native/server/ApacheSupport/2.2/linux/Makefile.am b/CASA-auth-token/native/server/ApacheSupport/2.2/linux/Makefile.am new file mode 100644 index 00000000..243c5d6f --- /dev/null +++ b/CASA-auth-token/native/server/ApacheSupport/2.2/linux/Makefile.am @@ -0,0 +1,114 @@ +####################################################################### +# +# 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 +else +TARGET_CFG = Release +endif + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../../../.. + +LIBDIR = $(ROOT)/$(LIB) +APACHEINCLUDE = /usr/include/apache2 +APACHELIB = /usr/lib/apache2 +APRINCLUDE = /usr/include/apr-1 +APRLIB = /usr/lib/apr-1 + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +PLATFORMINDEPENDENTSOURCEDIR = .. +PLATFORMDEPENDENTSOURCEDIR = . + +MODULE_NAME = mod_authn_casa +MODULE_EXT = so + +CFILES = ../mod_authn_casa.c + +CSFILES_CSC := +INCLUDES = -I. -I$(ROOT)/include -I$(APACHEINCLUDE) -I$(APRINCLUDE) +RESOURCES = +DEFINES = -Wno-format-extra-args -fno-strict-aliasing + +CFLAGS += $(INCLUDES) $(DEFINES) -D_LARGEFILE64_SOURCE +LIBS = -lpthread -lcasa_s_authtoken -lapr-1 -laprutil-1 +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(LIBDIR)/$(TARGET_CFG) -L$(APACHELIB) -L$(APRLIB) -Xlinker -rpath -Xlinker /opt/novell/CASA/lib + +OBJDIR = ./$(TARGET_CFG)/$(LIB) +OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) + +EXTRA_DIST = $(CFILES) + +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: +#cd $(TARGET_CFG); rm -rf *.dbg *.exe *.dll *.o *.so; cd ..; rmdir $(OBJDIR) + rm -rf $(TARGET_CFG) + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/native/server/ApacheSupport/2.2/mod_authn_casa.c b/CASA-auth-token/native/server/ApacheSupport/2.2/mod_authn_casa.c new file mode 100644 index 00000000..a0bb0342 --- /dev/null +++ b/CASA-auth-token/native/server/ApacheSupport/2.2/mod_authn_casa.c @@ -0,0 +1,478 @@ +/*********************************************************************** + * + * 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 "apr_strings.h" +#include "ap_config.h" +#include "ap_provider.h" +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_protocol.h" +#include "http_request.h" + +#include "mod_auth.h" + +#include "casa_s_authtoken.h" + +// +// Module per-dir configuration structure. +// +typedef struct _authn_casa_dir_cfg +{ + int performUsernameCheck; + +} authn_casa_dir_cfg; + + +// +// Forward declaration of our module structure. +// +module AP_MODULE_DECLARE_DATA authn_casa_module; + +// +// Environment variables set by module +// +static char CasaIdentityIdEnvVar[] = "IdentityId"; +static char CasaIdentitySourceNameEnvVar[] = "IdentityDataSourceName"; +static char CasaIdentitySourceUrlEnvVar[] = "IdentityDataSourceUrl"; + +// +// Function: create_per_dir_config() +// +// Create per-dir configuration structure. +// +static void* +create_per_dir_config( + apr_pool_t *p, + char *x) +{ + authn_casa_dir_cfg *pDirConfig; + + // Allocate space for our configuration structure + pDirConfig = (authn_casa_dir_cfg*) apr_palloc(p, sizeof(*pDirConfig)); + + // Return our new configuration structure + return (void*) pDirConfig; +} + +/* ************************************************************************ + * set_authn_casa_uname_check() + * + * Process UsernameCheck configuration directive.. + * + * L2 + * ************************************************************************/ +static const char* +set_authn_casa_uname_check( + cmd_parms *cmd, + void *cfg, + int arg) +{ + authn_casa_dir_cfg *pDirConfig = (authn_casa_dir_cfg*) cfg; + + // Record the value in our structure + pDirConfig->performUsernameCheck = arg; + + return NULL; +} + +// +// Configuration directives array structure. +// +static const command_rec authn_casa_cmds[] = +{ + AP_INIT_FLAG("UsernameCheck", // tbd - May be this directive should be on a per-directory or per-location basis + set_authn_casa_uname_check, + NULL, + OR_AUTHCFG, + "Check for username == CasaPrincipal (Value limited to 'on' or 'off')"), + {NULL} +}; + +/* ************************************************************************ + * check_password() + * + * Given a user and password, expected to return AUTH_GRANTED if we + * can validate the user/password combination. + * + * L2 + * ************************************************************************/ +static authn_status +check_password( + request_rec *r, + const char *user, + const char *password) +{ + authn_status retStatus; + authn_casa_dir_cfg *pDirConfig; + bool userNameChecked = false; + int i; + char *pLocationName; + + // First determine the length of the name of the location being protected + i = 0; + while (r->uri[i] != '\0') + { + if (r->uri[i] == '/') + { + // Ignore the slash if it is at the beginning of the uri + if (i != 0) + { + // The slash is not at the beggining of the uri, stop. + break; + } + } + + i++; + } + + // Now get a copy of the location being protected + if (i > 1) + { + pLocationName = apr_palloc(r->pool, i); + if (pLocationName) + { + memset(pLocationName, 0, i); + memcpy(pLocationName, &(r->uri[1]), i - 1); // Do not include the slashes + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure"); + return AUTH_GENERAL_ERROR; + } + } + else + { + // We are protecting the server root + pLocationName = "apache_root"; + } + + // Get access to our per-dir configuration structure + pDirConfig = ap_get_module_config(r->per_dir_config, + &authn_casa_module); + if (pDirConfig) + { + // Assume success + retStatus = AUTH_GRANTED; + + // Check if we must perform the username check + if (pDirConfig->performUsernameCheck != 0) + { + // Remember that we performed this check + userNameChecked = true; + + // Check if the username matches the name what we are expecting + if (strcmp(user, "CasaPrincipal") != 0) + { + // The username does not match, allow other providers to get + // a crack to it. + retStatus = AUTH_USER_NOT_FOUND; + } + } + + // Check the token if a problem has not been found + if (retStatus == AUTH_GRANTED) + { + CasaStatus casaStatus; + PrincipalIf *pPrincipalIf; + + // Validate the token + casaStatus = ValidateAuthToken(pLocationName, + password, + strlen(password), + &pPrincipalIf); + if (CASA_SUCCESS(casaStatus)) + { + + int buffLen = 0; + apr_table_t *e = r->subprocess_env; + + // Associate necessary environment variables with the request block + casaStatus = pPrincipalIf->getIdentityId(pPrincipalIf, + NULL, + &buffLen); + if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + char *pBuff; + + // Allocate buffer to obtain the Identity Id + pBuff = apr_pcalloc(r->pool, buffLen); + if (pBuff) + { + // Read the value into our buffer + if (CASA_SUCCESS(pPrincipalIf->getIdentityId(pPrincipalIf, + pBuff, + &buffLen))) + { + // Now set the environment variable + apr_table_setn(e, CasaIdentityIdEnvVar, pBuff); + + // Also, update the username within the request block with the identity id + r->user = pBuff; + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Unable to obtain identity id"); + retStatus = AUTH_GENERAL_ERROR; + } + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure"); + retStatus = AUTH_GENERAL_ERROR; + } + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Un-expected error obtaining identity id, %08X", casaStatus); + retStatus = AUTH_GENERAL_ERROR; + } + + if (retStatus == AUTH_GRANTED) + { + buffLen = 0; + casaStatus = pPrincipalIf->getSourceName(pPrincipalIf, + NULL, + &buffLen); + if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + char *pBuff; + + // Allocate buffer to obtain the Identity Source Name + pBuff = apr_pcalloc(r->pool, buffLen); + if (pBuff) + { + // Read the value into our buffer + if (CASA_SUCCESS(pPrincipalIf->getSourceName(pPrincipalIf, + pBuff, + &buffLen))) + { + // Now set the environment variable + apr_table_setn(e, CasaIdentitySourceNameEnvVar, pBuff); + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Unable to obtain identity source name"); + retStatus = AUTH_GENERAL_ERROR; + } + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure"); + retStatus = AUTH_GENERAL_ERROR; + } + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Un-expected error obtaining identity source name, %08X", casaStatus); + retStatus = AUTH_GENERAL_ERROR; + } + } + + if (retStatus == AUTH_GRANTED) + { + buffLen = 0; + casaStatus = pPrincipalIf->getSourceUrl(pPrincipalIf, + NULL, + &buffLen); + if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + char *pBuff; + + // Allocate buffer to obtain the Identity Source Url + pBuff = apr_pcalloc(r->pool, buffLen); + if (pBuff) + { + // Read the value into our buffer + if (CASA_SUCCESS(pPrincipalIf->getSourceUrl(pPrincipalIf, + pBuff, + &buffLen))) + { + // Now set the environment variable + apr_table_setn(e, CasaIdentitySourceUrlEnvVar, pBuff); + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Unable to obtain identity source url"); + retStatus = AUTH_GENERAL_ERROR; + } + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure"); + retStatus = AUTH_GENERAL_ERROR; + } + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Un-expected error obtaining identity source url, %08X", casaStatus); + retStatus = AUTH_GENERAL_ERROR; + } + } + + if (retStatus == AUTH_GRANTED) + { + char *pAttribNameBuff, *pAttribValueBuff; + int enumHandle = 0; + int attribNameBuffLen, attribValueBuffLen; + + while (retStatus == AUTH_GRANTED) + { + // Get attribute lengths + attribNameBuffLen = attribValueBuffLen = 0; + casaStatus = pPrincipalIf->attributeEnumerate(pPrincipalIf, + &enumHandle, + NULL, + &attribNameBuffLen, + NULL, + &attribValueBuffLen); + if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + // Allocate buffers to obtain the attribute data + pAttribNameBuff = apr_pcalloc(r->pool, attribNameBuffLen); + pAttribValueBuff = apr_pcalloc(r->pool, attribValueBuffLen); + if (pAttribNameBuff && pAttribValueBuff) + { + // Read the attribute into our buffer + if (CASA_SUCCESS(pPrincipalIf->attributeEnumerate(pPrincipalIf, + &enumHandle, + pAttribNameBuff, + &attribNameBuffLen, + pAttribValueBuff, + &attribValueBuffLen))) + { + // Now set the environment variable + apr_table_setn(e, pAttribNameBuff, pAttribValueBuff); + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Unable to obtain identity attribute"); + retStatus = AUTH_GENERAL_ERROR; + } + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure"); + retStatus = AUTH_GENERAL_ERROR; + } + } + else + { + // Check if we are done going through the attributes + if (CasaStatusCode(casaStatus) == CASA_STATUS_NO_MORE_ENTRIES) + { + // Done + break; + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Un-expected error during attribute enumeration, %08X", casaStatus); + retStatus = AUTH_GENERAL_ERROR; + } + } + } + } + + // Release the principal interface instance + pPrincipalIf->releaseReference(pPrincipalIf); + } + else + { + // Check if the token validation failed for a CasaPrincipal + if (userNameChecked) + { + // Token validation failed for a CasaPrincipal, always return AUTH_DENIED. + retStatus = AUTH_DENIED; + } + else + { + // We did not check the username, set the return status based on the status + // returned by ValidateAuthToken(). + if (CasaStatusCode(casaStatus) == CASA_STATUS_AUTHENTICATION_FAILURE) + { + // Authentication failed + retStatus = AUTH_DENIED; + } + else + { + // Allow other providers to get a crack to it + retStatus = AUTH_USER_NOT_FOUND; + } + } + } + } + } + else + { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Did not get module per-server config structure"); + retStatus = AUTH_GENERAL_ERROR; + } + + return retStatus; +} + +// +// Authentication Provider Function Table +// +static const authn_provider authn_casa_provider = +{ + &check_password, + NULL, // We do not support Digest Authentication +}; + +/* ************************************************************************ + * register_hooks() + * + * Register all of the module hooks. + * + * L2 + * ************************************************************************/ +static void +register_hooks( + apr_pool_t *p) +{ + // Register as an authentication provider + ap_register_provider(p, + AUTHN_PROVIDER_GROUP, // Provider group + "casa", // Provider name + "0", // Provider version + &authn_casa_provider); // Authentication Provider function table +} + +// +// Declare ourselves to the HTTPD core. +// +module AP_MODULE_DECLARE_DATA authn_casa_module = +{ + STANDARD20_MODULE_STUFF, + create_per_dir_config, // Create per-dir config structures + NULL, // merge per-dir config structures + NULL, // Create per-server config structures + NULL, // merge per-server config structures + authn_casa_cmds, // command handlers + register_hooks // register hooks +}; diff --git a/CASA-auth-token/native/server/ApacheSupport/Makefile.am b/CASA-auth-token/native/server/ApacheSupport/Makefile.am new file mode 100644 index 00000000..5478d49a --- /dev/null +++ b/CASA-auth-token/native/server/ApacheSupport/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 = 2.2 + +DIST_SUBDIRS = 2.2 + +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/native/server/AuthTokenValidate/Makefile.am b/CASA-auth-token/native/server/AuthTokenValidate/Makefile.am new file mode 100644 index 00000000..42a71e9f --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/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) idenTokenProviders + +DIST_SUBDIRS = linux idenTokenProviders + +CFILES = + +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/native/server/AuthTokenValidate/README b/CASA-auth-token/native/server/AuthTokenValidate/README new file mode 100644 index 00000000..287f9dfc --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/README @@ -0,0 +1,77 @@ +/*********************************************************************** + * + * README for libcasa_s_authtoken + * + ***********************************************************************/ + +INTRODUCTION + +libcasa_s_authtoken provides an API for the validation of CASA Authentication Tokens. +The API provides a means for obtaining identity information about authenticated +entities. + +Applications should avoid calling directly into this library's APIs. Instead, applications +should code to the PAM API to validate authentication credentials or allow an external +module to perform the credential validation. To facilitate this, CASA Authentication +provides PAM, Apache, and JAAS modules that can be used to validate credentials containing +CASA Authentication tokens, + +CONFIGURING TRUSTED AUTHENTICATION TOKEN SERVICES + +tbd. Add info about the installation of public certificates and trusted certificate authorities. + +CONFIGURING ADDITIONAL IDENTITY TOKEN PROVIDER MODULES + +CASA Authentication Tokens contain Identity Tokens. The Identity Tokens contain the identity +information about the entity being authenticated. Identity Tokens can be of different types, +the type utilized for use with a particular service is configured at the time that the service +is configured for CASA Authentication. The default identity token type is CasaIdentityToken. + +libcasa_s_authtoken supports different identity token types through an API that allows for the +configuration of different Identity Token Provider plug-ins. An Identity Token Provider plug-in +is configured by placing a configuration file for the plug-ins in the +/etc/opt/CASA/authtoken.d/modules.d folder. The name of the plug-in configuration file is related +to the identity token type in the following manner: IdentityTokenTypeName.conf. + +Identity Token Provider plug-in configuration files must must contain a directive indicating the +path to the library implementing the Identity Token Provider plug-in (See the configuration file +for the CasaIdentityToken plug-in for an example). + +SERVER APPLICATION PROGRAMMING NOTES + +The Validate CASA Authentication Token API is defined in casa_s_authtoken.h. + +The API consists of a call to validate authentication tokens. The caller must supply a service +name which must match the service name provided by the client when requesting the authentication +token. Successful calls to the validate authentication token API will return a handle to a principal +interface object. The principal interface object handle can be used to obtain identity information +about the authenticated entity as well as information about the authentication realm. The principal +interface object must be released after it is no longer needed. The amount and type of identity +information associated with the principal interface is dependent on what is configured at the +time that the service is enabled for CASA Authentication. + +For examples of code which uses the Validate CASA Authentication Token API look at the implementations +of the CASA Authentication PAM module and the CASA Authentication Provider Apache module. + +IDENTITY TOKEN PROVIDER PROGRAMMING NOTES + +The Identity Token Provider API is defined in iden_token_provider.h. + +For an example see the implementation of the CASA Identity Token Provider. + +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/native/server/AuthTokenValidate/TODO b/CASA-auth-token/native/server/AuthTokenValidate/TODO new file mode 100644 index 00000000..2bf53b7a --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/TODO @@ -0,0 +1,15 @@ +/*********************************************************************** + * + * TODO for libcasa_s_authtoken + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for libcasa_s_authtoken. + +OUTSTANDING ITEMS + +- Change AuthTokens to be SOAP messages secured with WS-Security and WS-Trust. +- Implement CheckAuthToken(). +- Finish README documentation. diff --git a/CASA-auth-token/native/server/AuthTokenValidate/authtoken.c b/CASA-auth-token/native/server/AuthTokenValidate/authtoken.c new file mode 100644 index 00000000..d4ded26d --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/authtoken.c @@ -0,0 +1,693 @@ +/*********************************************************************** + * + * 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_SIGNATURE_DATA 0x2 +#define AWAITING_SIGNATURE_ELEMENT_START 0x3 +#define AWAITING_SIGNATURE_ELEMENT_END 0x4 +#define AWAITING_LIFETIME_DATA 0x5 +#define AWAITING_LIFETIME_ELEMENT_START 0x6 +#define AWAITING_LIFETIME_ELEMENT_END 0x7 +#define AWAITING_IDENT_TOKEN_ELEMENT_START 0x8 +#define AWAITING_IDENT_TOKEN_ELEMENT_END 0x9 +#define AWAITING_IDENT_TOKEN_DATA 0xA +#define AWAITING_TYPE_ELEMENT_START 0xB +#define AWAITING_TYPE_ELEMENT_END 0xC +#define AWAITING_TYPE_DATA 0xD +#define DONE_PARSING 0xE + +// +// Authentication Token Parse Structure +// +typedef struct _AuthTokenParse +{ + XML_Parser p; + int state; + int elementDataProcessed; + AuthToken *pAuthToken; + CasaStatus status; + +} AuthTokenParse, *PAuthTokenParse; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//++======================================================================= +static +void XMLCALL +AuthTokenStartElementHandler( + IN void *pUserData, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + AuthTokenParse *pAuthTokenParse = (AuthTokenParse*) pUserData; + + DbgTrace(2, "-AuthTokenStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pAuthTokenParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the Authentication + // Response Element. + if (strcmp(name, AUTH_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthTokenParse->state = AWAITING_SIGNATURE_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SIGNATURE_ELEMENT_START: + + // In this state, we are only expecting the Signature Element. + if (strcmp(name, SIGNATURE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthTokenParse->state = AWAITING_SIGNATURE_DATA; + } + else + { + DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthTokenParse->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. + pAuthTokenParse->state = AWAITING_LIFETIME_DATA; + } + else + { + DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_IDENT_TOKEN_ELEMENT_START: + + // In this state, we are only expecting the Identity Token Element. + if (strcmp(name, IDENTITY_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthTokenParse->state = AWAITING_TYPE_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TYPE_ELEMENT_START: + + // In this state, we are only expecting the Type Element. + if (strcmp(name, TYPE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthTokenParse->state = AWAITING_TYPE_DATA; + } + else + { + DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected state = %d\n", pAuthTokenParse->state); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-AuthTokenStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +ConsumeElementData( + IN AuthTokenParse *pAuthTokenParse, + 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 + pAuthTokenParse->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 = pAuthTokenParse->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(pAuthTokenParse->elementDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pAuthTokenParse->elementDataProcessed + len + 1); + memcpy(pNewBuf, + *ppElementData, + pAuthTokenParse->elementDataProcessed); + memcpy(pNewBuf + pAuthTokenParse->elementDataProcessed, s, len); + pAuthTokenParse->elementDataProcessed += len; + + // Swap the buffers + free(*ppElementData); + *ppElementData = pNewBuf; + + // Return the length of the element data buffer + *pElementDataLen = pAuthTokenParse->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 +AuthTokenCharDataHandler( + IN void *pUserData, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + AuthTokenParse *pAuthTokenParse = (AuthTokenParse*) pUserData; + + DbgTrace(2, "-AuthTokenCharDataHandler- Start\n", 0); + + // Just exit if being called to process LF and CR characters + if (len == 1 + && ((*s == '\n') || (*s == '\r'))) + { + goto exit; + } + + // Proceed based on the state + switch (pAuthTokenParse->state) + { + case AWAITING_SIGNATURE_DATA: + case AWAITING_SIGNATURE_ELEMENT_END: + + pAuthTokenParse->status = ConsumeElementData(pAuthTokenParse, + s, + len, + &pAuthTokenParse->pAuthToken->pSignature, + &pAuthTokenParse->pAuthToken->signatureLen); + if (CASA_SUCCESS(pAuthTokenParse->status)) + { + // Advanced to the next state + pAuthTokenParse->state = AWAITING_SIGNATURE_ELEMENT_END; + } + else + { + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_DATA: + case AWAITING_LIFETIME_ELEMENT_END: + + // Convert the lifetime string to a numeric value + pAuthTokenParse->pAuthToken->tokenLifetime = dtoul((char*) s, len); + + // Advanced to the next state + pAuthTokenParse->state = AWAITING_LIFETIME_ELEMENT_END; + break; + + case AWAITING_TYPE_DATA: + case AWAITING_TYPE_ELEMENT_END: + + pAuthTokenParse->status = ConsumeElementData(pAuthTokenParse, + s, + len, + &pAuthTokenParse->pAuthToken->pIdenTokenType, + &pAuthTokenParse->pAuthToken->idenTokenTypeLen); + if (CASA_SUCCESS(pAuthTokenParse->status)) + { + // Advanced to the next state + pAuthTokenParse->state = AWAITING_TYPE_ELEMENT_END; + } + else + { + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_IDENT_TOKEN_DATA: + case AWAITING_IDENT_TOKEN_ELEMENT_END: + + pAuthTokenParse->status = ConsumeElementData(pAuthTokenParse, + s, + len, + &pAuthTokenParse->pAuthToken->pIdenToken, + &pAuthTokenParse->pAuthToken->idenTokenLen); + if (CASA_SUCCESS(pAuthTokenParse->status)) + { + // Advanced to the next state + pAuthTokenParse->state = AWAITING_IDENT_TOKEN_ELEMENT_END; + } + else + { + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-AuthTokenCharDataHandler- Un-expected state = %d\n", pAuthTokenParse->state); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-AuthTokenCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +AuthTokenEndElementHandler( + IN void *pUserData, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + AuthTokenParse *pAuthTokenParse = (AuthTokenParse*) pUserData; + + DbgTrace(2, "-AuthTokenEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pAuthTokenParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the Authentication + // Token Element. + if (strcmp(name, AUTH_TOKEN_ELEMENT_NAME) == 0) + { + // Done. + pAuthTokenParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-AuthTokenEndHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SIGNATURE_ELEMENT_END: + + // In this state, we are only expecting the Signature Element. + if (strcmp(name, SIGNATURE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthTokenParse->state = AWAITING_LIFETIME_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthTokenParse->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. + pAuthTokenParse->state = AWAITING_IDENT_TOKEN_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TYPE_ELEMENT_END: + + // In this state, we are only expecting the Type Element. + if (strcmp(name, TYPE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthTokenParse->state = AWAITING_IDENT_TOKEN_DATA; + } + else + { + DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_IDENT_TOKEN_ELEMENT_END: + + // In this state, we are only expecting the Identity Token Element. + if (strcmp(name, IDENTITY_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthTokenParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected state = %d\n", pAuthTokenParse->state); + XML_StopParser(pAuthTokenParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-AuthTokenEndElementHandler- End\n", 0); +} + + +//++======================================================================= +CasaStatus +CreateAuthToken( + IN char *pTokenBuf, + IN int tokenBufLen, + INOUT AuthToken **ppAuthToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + AuthTokenParse authTokenParse = {0}; + AuthToken *pAuthToken; + + DbgTrace(1, "-CreateAuthToken- Start\n", 0); + + /* + * Authentication tokens have the following format: + * + * + * + * signature value + * lifetime value + * identity token typeidentity token data + * + * + */ + + // Allocate AuthToken object + pAuthToken = malloc(sizeof(*pAuthToken)); + if (pAuthToken) + { + XML_Parser p; + + // Initialize the AuthToken object and set it in the + // authentication response parse object. + memset(pAuthToken, 0, sizeof(*pAuthToken)); + authTokenParse.pAuthToken = pAuthToken; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + authTokenParse.p = p; + + // Initialize the status within the parse object + authTokenParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + AuthTokenStartElementHandler, + AuthTokenEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, AuthTokenCharDataHandler); + + + // Set our user data + XML_SetUserData(p, &authTokenParse); + + // Parse the document + if (XML_Parse(p, pTokenBuf, tokenBufLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (authTokenParse.state == DONE_PARSING) + { + // The parse operation succeded. + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-CreateAuthToken- Parse operation did not complete\n", 0); + + // Check if a status has been recorded + if (authTokenParse.status != CASA_STATUS_SUCCESS) + { + retStatus = authTokenParse.status; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + } + else + { + DbgTrace(0, "-CreateAuthToken- 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, "-CreateAuthToken- 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)) + { + *ppAuthToken = pAuthToken; + } + else + { + free(pAuthToken); + } + } + else + { + DbgTrace(0, "-CreateAuthToken- Memory allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-CreateAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +RelAuthToken( + IN AuthToken *pAuthToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-RelAuthToken- Start\n", 0); + + // Free the resources associated with the object + if (pAuthToken->pSignature) + free(pAuthToken->pSignature); + + if (pAuthToken->pIdenTokenType) + free(pAuthToken->pIdenTokenType); + + if (pAuthToken->pIdenToken) + free(pAuthToken->pIdenToken); + + free(pAuthToken); + + DbgTrace(1, "-RelAuthToken- End\n", 0); +} + + +//++======================================================================= +CasaStatus +CheckAuthToken( + IN AuthToken *pAuthToken, + IN const char *pServiceName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + + DbgTrace(1, "-CheckuthToken- Start\n", 0); + + // tbd + + DbgTrace(1, "-CheckAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/config.c b/CASA-auth-token/native/server/AuthTokenValidate/config.c new file mode 100644 index 00000000..0fe71332 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/config.c @@ -0,0 +1,764 @@ +/*********************************************************************** + * + * 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; + +// Synchronization mutex +static +HANDLE g_configIfMutex = NULL; + + +//++======================================================================= +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); +} + + +//++======================================================================= +static +int SSCS_CALL +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, "-AddReference- Start\n", 0); + + // Increment the reference count on the object + PlatAcquireMutex(g_configIfMutex); + pConfigIfInstance->refCount ++; + refCount = pConfigIfInstance->refCount; + PlatReleaseMutex(g_configIfMutex); + + DbgTrace(2, "-AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +static +void SSCS_CALL +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, "-ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + PlatAcquireMutex(g_configIfMutex); + pConfigIfInstance->refCount --; + if (pConfigIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numConfigIfObjs --; + RemoveEntryList(&pConfigIfInstance->listEntry); + } + PlatReleaseMutex(g_configIfMutex); + + // 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, "-ReleaseReference- End\n", 0); +} + + +//++======================================================================= +static +char* SSCS_CALL +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 = strlen(pKeyName); + char *pKeyNameLowercase; + + DbgTrace(2, "-GetEntryValue- Start\n", 0); + + // Allocate enough space to hold lower case version of the key name + pKeyNameLowercase = 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 = malloc(pConfigKey->valueLen + 1); + if (pValue) + { + strcpy(pValue, pConfigKey->pValue); + } + else + { + DbgTrace(0, "-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, "-GetEntryValue- Buffer allocation failure\n", 0); + } + + DbgTrace(2, "-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 = strlen(pConfigFolder); + int configNameLen = 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); + + PlatAcquireMutex(g_configIfMutex); + + // 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 = malloc(configFolderLen + 1 + configNameLen + sizeof(".conf")); + if (pFilePath) + { + FILE *pConfigFile; + + strcpy(pFilePath, pConfigFolder); + strcat(pFilePath, "/"); + 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 = 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 = AddReference; + pConfigIfInstance->configIf.releaseReference = ReleaseReference; + pConfigIfInstance->configIf.getEntryValue = GetEntryValue; + + // Save the ConfigFolder and ConfigName information within the instance data + pConfigIfInstance->pConfigFolder = malloc(configFolderLen + 1); + if (pConfigIfInstance->pConfigFolder) + { + strcpy(pConfigIfInstance->pConfigFolder, pConfigFolder); + pConfigIfInstance->configFolderLen = configFolderLen; + + pConfigIfInstance->pConfigName = 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 = 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 = malloc(sizeof(*pConfigKey)); + if (pConfigKey) + { + pConfigKey->keyNameLen = strlen(pKey); + pConfigKey->pKeyName = malloc(pConfigKey->keyNameLen + 1); + if (pConfigKey->pKeyName) + { + // Save the key name in lower case + LowerCaseString(pConfigKey->pKeyName, pKey); + + pConfigKey->valueLen = strlen(pValue); + pConfigKey->pValue = 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(1, "-GetConfigInterface- Unable to open config file, errno = %d\n", errno); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation error\n", 0); + } + } + + PlatReleaseMutex(g_configIfMutex); + + DbgTrace(2, "-GetConfigInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +ConfigIfInit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Initializes the configuration interface complex. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + + DbgTrace(1, "-ConfigIfInit- Start\n", 0); + + // Allocate mutex + if ((g_configIfMutex = PlatAllocMutex()) != NULL) + retStatus = CASA_STATUS_SUCCESS; + else + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + + DbgTrace(1, "-ConfigIfInit- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +ConfigIfUninit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Uninitializes the configuration interface complex. +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-ConfigIfUninit- Start\n", 0); + + // Free mutex if necessary + if (g_configIfMutex) + { + PlatDestroyMutex(g_configIfMutex); + g_configIfMutex = NULL; + } + + DbgTrace(1, "-ConfigIfUninit- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/config_if.h b/CASA-auth-token/native/server/AuthTokenValidate/config_if.h new file mode 100644 index 00000000..0cdf31ce --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/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/native/server/AuthTokenValidate/idenTokenProviders/Makefile.am b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/Makefile.am new file mode 100644 index 00000000..2fb64053 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = casa + +DIST_SUBDIRS = casa + +CFILES = + +EXTRA_DIST = $(CFILES) + +.PHONY: package package-clean package-install package-uninstall +package package-clean package-install package-uninstall: + $(MAKE) -C $(TARGET_OS) $@ + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/Makefile.am b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/Makefile.am new file mode 100644 index 00000000..331523b2 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/Makefile.am @@ -0,0 +1,37 @@ +####################################################################### +# +# Copyright (C) 2006 Novell, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free +# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# Author: Juan Carlos Luciani +# +####################################################################### + +SUBDIRS = $(TARGET_OS) + +DIST_SUBDIRS = linux + +CFILES = + +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/native/server/AuthTokenValidate/idenTokenProviders/casa/README b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/README new file mode 100644 index 00000000..e40a2516 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/README @@ -0,0 +1,39 @@ +/*********************************************************************** + * + * README for casa_identoken + * + ***********************************************************************/ + +INTRODUCTION + +casa_identoken is the Identity Token Provider plug-in for tokens of type +CasaIdentityToken. This are the default identity tokens utilized by CASA +Authentication. + +CONFIGURATION + +The path to the casa_identoken plug-in is configured by placing the file +CasaIdentityToken.conf in the /etc/opt/CASA/authtoken.d/modules.d folder. + +PROGRAMMING NOTES + +This module does not provide APIs to components outside of the CASA +Authentication framework. + +SECURITY CONSIDERATIONS + +CasaIdentityTokens are embedded inside CASA Authentication Tokens. CasaIdentityTokens +contain identity information which may be confidential and no attempts are made to +ensure the confidentiality of the data. Because of this it is important that CASA +Authentication Tokens be secured by applications making use of them. It is recommended +that CASA authentication tokens be transmitted using SSL. + + + + + + + + + + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/TODO b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/TODO new file mode 100644 index 00000000..1a79afa0 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/TODO @@ -0,0 +1,13 @@ +/*********************************************************************** + * + * TODO for casa_identoken + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for casa_identoken. + +OUTSTANDING ITEMS + +None. diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/identoken.c b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/identoken.c new file mode 100644 index 00000000..f9636b6b --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/identoken.c @@ -0,0 +1,1458 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// XML Constants for the CASA Identity Token +// +#define CASA_IDENT_TOKEN_ELEMENT_NAME "casa_ident_tok" +#define ID_ELEMENT_NAME "id" +#define SOURCE_NAME_ELEMENT_NAME "source_name" +#define SOURCE_URL_ELEMENT_NAME "source_url" +#define TARGET_SERVICE_ELEMENT_NAME "target_service" +#define TARGET_HOST_ELEMENT_NAME "target_host" +#define ATTRIBUTES_ELEMENT_NAME "attributes" + +// +// Parse states +// +#define AWAITING_ROOT_ELEMENT_START 0x0 +#define AWAITING_ROOT_ELEMENT_END 0x1 +#define AWAITING_ID_DATA 0x2 +#define AWAITING_ID_ELEMENT_START 0x3 +#define AWAITING_ID_ELEMENT_END 0x4 +#define AWAITING_SOURCE_NAME_DATA 0x5 +#define AWAITING_SOURCE_NAME_ELEMENT_START 0x6 +#define AWAITING_SOURCE_NAME_ELEMENT_END 0x7 +#define AWAITING_SOURCE_URL_DATA 0x8 +#define AWAITING_SOURCE_URL_ELEMENT_START 0x9 +#define AWAITING_SOURCE_URL_ELEMENT_END 0xA +#define AWAITING_TARGET_SERVICE_DATA 0xB +#define AWAITING_TARGET_SERVICE_ELEMENT_START 0xC +#define AWAITING_TARGET_SERVICE_ELEMENT_END 0xD +#define AWAITING_TARGET_HOST_DATA 0xE +#define AWAITING_TARGET_HOST_ELEMENT_START 0xF +#define AWAITING_TARGET_HOST_ELEMENT_END 0x10 +#define AWAITING_ATTRIBUTES_ELEMENT_START 0x11 +#define AWAITING_ATTRIBUTE_DATA 0x12 +#define AWAITING_ATTRIBUTE_START 0x13 +#define AWAITING_ATTRIBUTE_END 0x14 +#define DONE_PARSING 0x15 + +// +// Attribute structure +// +typedef struct _Attribute +{ + LIST_ENTRY listEntry; + char *pAttribName; + int attribNameLen; + char *pAttribValue; + int attribValueLen; + +} Attribute, *PAttribute; + + +// +// Identity Token Interface instance data +// +typedef struct _IdenTokenIfInstance +{ + int refCount; + char *pIdentId; + int identIdLen; + char *pIdentSourceName; + int identSourceNameLen; + char *pIdentSourceUrl; + int identSourceUrlLen; + char *pTargetService; + int targetServiceLen; + char *pTargetHost; + int targetHostLen; + LIST_ENTRY attributeListHead; + IdenTokenIf idenTokenIf; + +} IdenTokenIfInstance, *PIdenTokenIfInstance; + + +// +// Identity Token Parse Structure +// +typedef struct _IdenTokenParse +{ + XML_Parser p; + int state; + int elementDataProcessed; + IdenTokenIfInstance *pIdenTokenIfInstance; + CasaStatus status; + +} IdenTokenParse, *PIdenTokenParse; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// IdenTokenIf variables +static +int g_numIdenTokenIfObjs = 0; + +// Synchronization mutex +static +HANDLE g_idenTokenIfMutex = NULL; + + +//++======================================================================= +static +void +FreeIdenTokenIfInstance( + IN IdenTokenIfInstance *pIdenTokenIfInstance) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + LIST_ENTRY *pListEntry; + + DbgTrace(2, "-FreeIdenTokenIfInstance- Start\n", 0); + + // Free all of the resources associated with the IdenTokenIfInstance + if (pIdenTokenIfInstance->pIdentId) + free(pIdenTokenIfInstance->pIdentId); + + if (pIdenTokenIfInstance->pIdentSourceName) + free(pIdenTokenIfInstance->pIdentSourceName); + + if (pIdenTokenIfInstance->pIdentSourceUrl) + free(pIdenTokenIfInstance->pIdentSourceUrl); + + if (pIdenTokenIfInstance->pTargetService) + free(pIdenTokenIfInstance->pTargetService); + + if (pIdenTokenIfInstance->pTargetHost) + free(pIdenTokenIfInstance->pTargetHost); + + // Go through all of the associated attributes + pListEntry = pIdenTokenIfInstance->attributeListHead.Flink; + while (pListEntry != &pIdenTokenIfInstance->attributeListHead) + { + Attribute *pAttribute = CONTAINING_RECORD(pListEntry, Attribute, listEntry); + + // Free resources associated with the attribute + if (pAttribute->pAttribName) + free(pAttribute->pAttribName); + + if (pAttribute->pAttribValue) + free(pAttribute->pAttribValue); + + // Forget about this attribute + RemoveEntryList(&pAttribute->listEntry); + free(pAttribute); + + // Start from the top again + pListEntry = pIdenTokenIfInstance->attributeListHead.Flink; + } + + // Free the identity token if instance structure + free(pIdenTokenIfInstance); + + DbgTrace(2, "-FreeIdenTokenIfInstance- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +IdenTokenStartElementHandler( + IN void *pUserData, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData; + Attribute *pAttribute; + + DbgTrace(2, "-IdenTokenStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pIdenTokenParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the CASA Identity + // Token Element. + if (strcmp(name, CASA_IDENT_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ID_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ID_ELEMENT_START: + + // In this state, we are only expecting the ID Element. + if (strcmp(name, ID_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ID_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_NAME_ELEMENT_START: + + // In this state, we are only expecting the Source Name Element. + if (strcmp(name, SOURCE_NAME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_SOURCE_NAME_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_URL_ELEMENT_START: + + // In this state, we are only expecting the Source Url Element. + if (strcmp(name, SOURCE_URL_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_SOURCE_URL_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_SERVICE_ELEMENT_START: + + // In this state, we are only expecting the Target Service Element. + if (strcmp(name, TARGET_SERVICE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_TARGET_SERVICE_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_HOST_ELEMENT_START: + + // In this state, we are only expecting the Target Host Element. + if (strcmp(name, TARGET_HOST_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_TARGET_HOST_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ATTRIBUTES_ELEMENT_START: + + // In this state, we are only expecting the Attributes Element. + if (strcmp(name, ATTRIBUTES_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ATTRIBUTE_START; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ATTRIBUTE_START: + + // Allocate an initialize Attribute structure + pAttribute = malloc(sizeof(*pAttribute)); + if (pAttribute) + { + memset(pAttribute, 0, sizeof(*pAttribute)); + InsertTailList(&pIdenTokenParse->pIdenTokenIfInstance->attributeListHead, + &pAttribute->listEntry); + + // Now save the attribute name + pAttribute->attribNameLen = strlen(name) + 1; + pAttribute->pAttribName = malloc(pAttribute->attribNameLen); + if (pAttribute->pAttribName) + { + strcpy(pAttribute->pAttribName, name); + + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ATTRIBUTE_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Buffer allocation failure\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Buffer allocation failure\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected state = %d\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-IdenTokenStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +ConsumeElementData( + IN IdenTokenParse *pIdenTokenParse, + 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 + pIdenTokenParse->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 = pIdenTokenParse->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(pIdenTokenParse->elementDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pIdenTokenParse->elementDataProcessed + len + 1); + memcpy(pNewBuf, + *ppElementData, + pIdenTokenParse->elementDataProcessed); + memcpy(pNewBuf + pIdenTokenParse->elementDataProcessed, s, len); + pIdenTokenParse->elementDataProcessed += len; + + // Swap the buffers + free(*ppElementData); + *ppElementData = pNewBuf; + + // Return the length of the element data buffer + *pElementDataLen = pIdenTokenParse->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 +IdenTokenCharDataHandler( + IN void *pUserData, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData; + Attribute *pAttribute; + + DbgTrace(2, "-IdenTokenCharDataHandler- Start\n", 0); + + // Just exit if being called to process LF and CR characters + if (len == 1 + && ((*s == '\n') || (*s == '\r'))) + { + goto exit; + } + + // Proceed based on the state + switch (pIdenTokenParse->state) + { + case AWAITING_ID_DATA: + case AWAITING_ID_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pIdentId, + &pIdenTokenParse->pIdenTokenIfInstance->identIdLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_ID_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_NAME_DATA: + case AWAITING_SOURCE_NAME_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pIdentSourceName, + &pIdenTokenParse->pIdenTokenIfInstance->identSourceNameLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_SOURCE_NAME_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_URL_DATA: + case AWAITING_SOURCE_URL_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pIdentSourceUrl, + &pIdenTokenParse->pIdenTokenIfInstance->identSourceUrlLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_SOURCE_URL_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_SERVICE_DATA: + case AWAITING_TARGET_SERVICE_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pTargetService, + &pIdenTokenParse->pIdenTokenIfInstance->targetServiceLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_TARGET_SERVICE_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_HOST_DATA: + case AWAITING_TARGET_HOST_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pTargetHost, + &pIdenTokenParse->pIdenTokenIfInstance->targetHostLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_TARGET_HOST_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ATTRIBUTE_DATA: + case AWAITING_ATTRIBUTE_END: + + // Get a pointer to current attribute structure + pAttribute = CONTAINING_RECORD(pIdenTokenParse->pIdenTokenIfInstance->attributeListHead.Blink, + Attribute, + listEntry); + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pAttribute->pAttribValue, + &pAttribute->attribValueLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_ATTRIBUTE_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-IdenTokenCharDataHandler- Un-expected state = %d\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-IdenTokenCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +IdenTokenEndElementHandler( + IN void *pUserData, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData; + + DbgTrace(2, "-IdenTokenEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pIdenTokenParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the CASA Identity + // Token Element. + if (strcmp(name, CASA_IDENT_TOKEN_ELEMENT_NAME) == 0) + { + // Done. + pIdenTokenParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ID_ELEMENT_END: + + // In this state, we are only expecting the Id Element. + if (strcmp(name, ID_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_SOURCE_NAME_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_NAME_ELEMENT_END: + + // In this state, we are only expecting the Source Name Element. + if (strcmp(name, SOURCE_NAME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_SOURCE_URL_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_URL_ELEMENT_END: + + // In this state, we are only expecting the Source URL Element. + if (strcmp(name, SOURCE_URL_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_TARGET_SERVICE_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_SERVICE_ELEMENT_END: + + // In this state, we are only expecting the Target Service Element. + if (strcmp(name, TARGET_SERVICE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_TARGET_HOST_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_HOST_ELEMENT_END: + + // In this state, we are only expecting the Target Host Element. + if (strcmp(name, TARGET_HOST_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ATTRIBUTES_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ATTRIBUTE_END: + + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ATTRIBUTE_START; + break; + + case AWAITING_ATTRIBUTE_START: + + // We should we done with the attributes, in this state we are only expecting + // the Attributes element. + if (strcmp(name, ATTRIBUTES_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-IdenTokenEndElementHandler- Un-expected state = %d\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-IdenTokenEndElementHandler- End\n", 0); +} + + +//++======================================================================= +static +int SSCS_CALL +AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-AddReference- Start\n", 0); + + // Increment the reference count on the object + PlatAcquireMutex(g_idenTokenIfMutex); + pIdenTokenIfInstance->refCount ++; + refCount = pIdenTokenIfInstance->refCount; + PlatReleaseMutex(g_idenTokenIfMutex); + + DbgTrace(2, "-AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +static +void SSCS_CALL +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; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + PlatAcquireMutex(g_idenTokenIfMutex); + pIdenTokenIfInstance->refCount --; + if (pIdenTokenIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numIdenTokenIfObjs --; + } + PlatReleaseMutex(g_idenTokenIfMutex); + + // Free object if necessary + if (freeObj) + { + FreeIdenTokenIfInstance(pIdenTokenIfInstance); + } + + DbgTrace(2, "-ReleaseReference- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus SSCS_CALL +GetIdentityId( + IN const void *pIfInstance, + INOUT char *pIdentIdBuf, + INOUT int *pIdentIdLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pIdentIdBuf - +// Pointer to buffer that will receive the identity id. The returned +// id will be in the form of a NULL terminated string. +// +// pIdentIdBufLen - +// Pointer to variable with the length of the buffer pointed by +// pIdentIdBuf. On exit it contains the length of the returned id +// (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the identity id associated with the identity token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-GetIdentityId- Start\n", 0); + + // Check the input parameters + if (pIfInstance == NULL + || pIdentIdLen == NULL + || (pIdentIdBuf == NULL && *pIdentIdLen != 0)) + { + DbgTrace(0, "-GetIdentityId- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Determine if the caller's buffer is large enough + if (*pIdentIdLen >= pIdenTokenIfInstance->identIdLen) + { + // Return the data to the caller + memcpy(pIdentIdBuf, pIdenTokenIfInstance->pIdentId, pIdenTokenIfInstance->identIdLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the lenght of the id + *pIdentIdLen = pIdenTokenIfInstance->identIdLen; + +exit: + + DbgTrace(2, "-GetIdentityId- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus SSCS_CALL +GetSourceName( + IN const void *pIfInstance, + INOUT char *pSourceNameBuf, + INOUT int *pSourceNameLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pSourceNameBuf - +// Pointer to buffer that will receive the name associated with the +// identity information source. The returned name will be in the form +// of a NULL terminated string. +// +// pSourceNameBufLen - +// Pointer to variable with the length of the buffer pointed by +// pSourceNameBuf. On exit it contains the length of the returned +// name (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the name of the identity source associated with the identity token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-GetSourceName- Start\n", 0); + + // Check the input parameters + if (pIfInstance == NULL + || pSourceNameLen == NULL + || (pSourceNameBuf == NULL && *pSourceNameLen != 0)) + { + DbgTrace(0, "-GetSourceName- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Determine if the caller's buffer is large enough + if (*pSourceNameLen >= pIdenTokenIfInstance->identSourceNameLen) + { + // Return the data to the caller + memcpy(pSourceNameBuf, pIdenTokenIfInstance->pIdentSourceName, pIdenTokenIfInstance->identSourceNameLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the lenght of the source name + *pSourceNameLen = pIdenTokenIfInstance->identSourceNameLen; + +exit: + + DbgTrace(2, "-GetSourceName- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus SSCS_CALL +GetSourceUrl( + IN const void *pIfInstance, + INOUT char *pSourceUrlBuf, + INOUT int *pSourceUrlLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pSourceUrlBuf - +// Pointer to buffer that will receive the URL associated with the +// identity information source. The returned URL will be in the form +// of a NULL terminated string. +// +// pSourceUrlBufLen - +// Pointer to variable with the length of the buffer pointed by +// pSourceUrlBuf. On exit it contains the length of the returned +// URL (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the URL to the identity source associated with the identity token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-GetSourceUrl- Start\n", 0); + + // Check the input parameters + if (pIfInstance == NULL + || pSourceUrlLen == NULL + || (pSourceUrlBuf == NULL && *pSourceUrlLen != 0)) + { + DbgTrace(0, "-GetSourceUrl- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Determine if the caller's buffer is large enough + if (*pSourceUrlLen >= pIdenTokenIfInstance->identSourceUrlLen) + { + // Return the data to the caller + memcpy(pSourceUrlBuf, pIdenTokenIfInstance->pIdentSourceUrl, pIdenTokenIfInstance->identSourceUrlLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the lenght of the source url + *pSourceUrlLen = pIdenTokenIfInstance->identSourceUrlLen; + +exit: + + DbgTrace(2, "-GetSourceUrl- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus SSCS_CALL +AttributeEnumerate( + IN const void *pIfInstance, + INOUT int *pEnumHandle, + INOUT char *pAttribNameBuf, + INOUT int *pAttribNameLen, + INOUT char *pAttribValueBuf, + INOUT int *pAttribValueLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pEnumHandle - +// Pointer to enumeration handle. Must be set to 0 to start an +// enumeration. Note the enumeration handle advances if the +// function returns success. +// +// pAttribNameBuf - +// Pointer to buffer that will receive the identity attribute name. The +// returned name will be in the form of a NULL terminated string. +// +// pAttribNameLen - +// Pointer to variable with the length of the buffer pointed by +// pAttribNameBuf. On exit it contains the length of the returned +// name (including the NULL terminator). +// +// pAttribValueBuf - +// Pointer to buffer that will receive the identity attribute value. The +// returned value will be in the form of a NULL terminated string. +// +// pAttribValueLen - +// Pointer to variable with the length of the buffer pointed by +// pAttribValueBuf. On exit it contains the length of the returned +// value (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Enumerates through the attributes associated with the identity token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + LIST_ENTRY *pListEntry; + int i; + Attribute *pAttribute; + + DbgTrace(2, "-AttributeEnumerate- Start\n", 0); + + // Check the input parameters + if (pIfInstance == NULL + || pEnumHandle == NULL + || pAttribNameLen == NULL + || pAttribValueLen == NULL + || (pAttribNameBuf == NULL && *pAttribNameLen != 0) + || (pAttribValueBuf == NULL && *pAttribValueLen != 0)) + { + DbgTrace(0, "-AttributeEnumerate- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Find the appropriate attribute based on the enum handle which is used as + // an index. + i = 0; + pAttribute = NULL; + pListEntry = pIdenTokenIfInstance->attributeListHead.Flink; + while (pListEntry != &pIdenTokenIfInstance->attributeListHead) + { + // Is this the attribute needed + if (i == *pEnumHandle) + { + // This is the attribute needed + pAttribute = CONTAINING_RECORD(pListEntry, Attribute, listEntry); + break; + } + else + { + // No, try the next one. + pListEntry = pListEntry->Flink; + i++; + } + } + + // Check if we found an attribute for the indicated enum handle + if (pAttribute) + { + // Try to return the attribute name + if (*pAttribNameLen >= pAttribute->attribNameLen) + { + // Return the attribute name + memcpy(pAttribNameBuf, pAttribute->pAttribName, pAttribute->attribNameLen); + + // Now, try to return the attribute value + if (*pAttribValueLen >= pAttribute->attribValueLen) + { + // Return the attribute value + memcpy(pAttribValueBuf, pAttribute->pAttribValue, pAttribute->attribValueLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + + // Advance the enum handle + *pEnumHandle = *pEnumHandle + 1; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the attribute lengths + *pAttribNameLen = pAttribute->attribNameLen; + *pAttribValueLen = pAttribute->attribValueLen; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_NO_MORE_ENTRIES); + } + +exit: + + DbgTrace(2, "-AttributeEnumerate- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +GetIdenTokenInterface( + IN const char *pTokenBuf, + IN const int tokenLen, + INOUT IdenTokenIf **ppIdenTokenIf) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Get principal interface instanced for the identity associated +// with specified identity token. +// +// L2 +//=======================================================================-- +{ + IdenTokenIfInstance *pIdenTokenIfInstance; + CasaStatus retStatus; + + DbgTrace(2, "-GetIdenTokenInterface- Start\n", 0); + + // Create a IdenTokenIfInstance object for it. + pIdenTokenIfInstance = malloc(sizeof(*pIdenTokenIfInstance)); + if (pIdenTokenIfInstance) + { + XML_Parser p; + IdenTokenParse idenTokenParse = {0}; + + /* + * CASA identity tokens have the following format: + * + * + * + * identity id + * identity data source name + * identity data source url + * target service name + * target host name + * + * attribute value + * attribute value + * ... + * + * + * + */ + + // Initialize the IdentTokenIfInstance object and set it in the + // idenTokenParse object. + memset(pIdenTokenIfInstance, 0, sizeof(*pIdenTokenIfInstance)); + InitializeListHead(&pIdenTokenIfInstance->attributeListHead); + pIdenTokenIfInstance->idenTokenIf.addReference = AddReference; + pIdenTokenIfInstance->idenTokenIf.releaseReference = ReleaseReference; + pIdenTokenIfInstance->idenTokenIf.getIdentityId = GetIdentityId; + pIdenTokenIfInstance->idenTokenIf.getSourceName = GetSourceName; + pIdenTokenIfInstance->idenTokenIf.getSourceUrl = GetSourceUrl; + pIdenTokenIfInstance->idenTokenIf.attributeEnumerate = AttributeEnumerate; + + idenTokenParse.pIdenTokenIfInstance = pIdenTokenIfInstance; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + idenTokenParse.p = p; + + // Initialize the status within the parse object + idenTokenParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + IdenTokenStartElementHandler, + IdenTokenEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, IdenTokenCharDataHandler); + + + // Set our user data + XML_SetUserData(p, &idenTokenParse); + + // Parse the document + if (XML_Parse(p, pTokenBuf, tokenLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (idenTokenParse.state == DONE_PARSING) + { + // The parse operation succeded. + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetIdenTokenInterface- Parse operation did not complete\n", 0); + + // Check if a status has been recorded + if (idenTokenParse.status != CASA_STATUS_SUCCESS) + { + retStatus = idenTokenParse.status; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + } + else + { + DbgTrace(0, "-GetIdenTokenInterface- 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, "-CreateAuthToken- Parser creation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + + // Return the Identity Token Interface to the caller if successful + if (CASA_SUCCESS(retStatus)) + { + // Return the IdenTokenIf associated with the instance data after + // incrementing its reference count. + pIdenTokenIfInstance->refCount ++; + *ppIdenTokenIf = &pIdenTokenIfInstance->idenTokenIf; + + // Bump up our interface instance count + PlatAcquireMutex(g_idenTokenIfMutex); + g_numIdenTokenIfObjs ++; + PlatReleaseMutex(g_idenTokenIfMutex); + } + else + { + FreeIdenTokenIfInstance(pIdenTokenIfInstance); + } + } + else + { + DbgTrace(0, "-GetIdenTokenInterface- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(2, "-GetIdenTokenInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +IdenTokenIfInit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Initializes the identity token interface complex. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + + DbgTrace(1, "-IdenTokenIfInit- Start\n", 0); + + // Allocate mutex + if ((g_idenTokenIfMutex = PlatAllocMutex()) != NULL) + retStatus = CASA_STATUS_SUCCESS; + else + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + + DbgTrace(1, "-IdenTokenIfInit- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +IdenTokenIfUninit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Uninitializes the configuration interface complex. +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-IdenTokenIfUninit- Start\n", 0); + + // Free mutex if necessary + if (g_idenTokenIfMutex) + { + PlatDestroyMutex(g_idenTokenIfMutex); + g_idenTokenIfMutex = NULL; + } + + DbgTrace(1, "-IdenTokenIfUninit- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/identokenprovider.c b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/identokenprovider.c new file mode 100644 index 00000000..072f6372 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/identokenprovider.c @@ -0,0 +1,346 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Identity Token Provider Interface instance data +// +typedef struct _IdenTokenProviderIfInstance +{ + int refCount; + IdenTokenProviderIf idenTokenProviderIf; + +} IdenTokenProviderIfInstance, *PIdenTokenProviderIfInstance; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// IdenTokenProviderIf variables +static +int g_numIdenTokenProviderIfObjs = 0; + +// Debug Level +int DebugLevel = 0; + +// +// Initialization variables +// +static +bool g_moduleInitialized = false; + +// Synchronization mutex +static +HANDLE g_idenTokenProviderIfMutex = NULL; + + +//++======================================================================= +static +int SSCS_CALL +AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + IdenTokenProviderIfInstance *pIdenTokenProviderIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenProviderIfInstance, idenTokenProviderIf); + + DbgTrace(2, "-AddReference- Start\n", 0); + + // Increment the reference count on the object + PlatAcquireMutex(g_idenTokenProviderIfMutex); + pIdenTokenProviderIfInstance->refCount ++; + refCount = pIdenTokenProviderIfInstance->refCount; + PlatReleaseMutex(g_idenTokenProviderIfMutex); + + DbgTrace(2, "-AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +static +void SSCS_CALL +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; + IdenTokenProviderIfInstance *pIdenTokenProviderIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenProviderIfInstance, idenTokenProviderIf); + + DbgTrace(2, "-ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + PlatAcquireMutex(g_idenTokenProviderIfMutex); + pIdenTokenProviderIfInstance->refCount --; + if (pIdenTokenProviderIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numIdenTokenProviderIfObjs --; + } + PlatReleaseMutex(g_idenTokenProviderIfMutex); + + // Free object if necessary + if (freeObj) + free(pIdenTokenProviderIfInstance); + + DbgTrace(2, "-ReleaseReference- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +GetIdentityTokenIf( + IN const void *pIfInstance, + IN const char *pTokenBuf, + IN const int tokenLen, + INOUT IdenTokenIf **ppIdenTokenIf) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pTokenBuf - +// Pointer to null terminated string containing an identity token. +// +// tokenLen - +// Length of the token contained in the token buffer. +// +// ppIdenTokenIf - +// Pointer to variable that will receive pointer to identity +// token interface. +// +// Returns: +// Casa Status +// +// Description: +// Get identity token interface instance for the specified token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + char *pDecodedTokenBuf; + int decodedTokenBufLen; + + DbgTrace(2, "-GetIdentityTokenIf- Start\n", 0); + + // Validate input parameters + if (pIfInstance == NULL + || pTokenBuf == NULL + || tokenLen == 0 + || ppIdenTokenIf == NULL) + { + DbgTrace(0, "-GetIdentityTokenIf- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // First decode the token string + retStatus = DecodeData(pTokenBuf, + tokenLen, + (void**) &pDecodedTokenBuf, + &decodedTokenBufLen); + if (CASA_SUCCESS(retStatus)) + { + // Get the identity token interface + retStatus = GetIdenTokenInterface(pDecodedTokenBuf, + decodedTokenBufLen, + ppIdenTokenIf); + + // Free the decoded token buffer + free(pDecodedTokenBuf); + } + else + { + DbgTrace(0, "-GetIdentityTokenIf- Token decode failure\n", 0); + } + +exit: + + DbgTrace(2, "-GetIdentityTokenIf- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus SSCS_CALL +GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN( + IN const ConfigIf *pModuleConfigIf, + INOUT IdenTokenProviderIf **ppIdenTokenProviderIf) +// +// Arguments: +// pModuleConfigIf - +// Pointer to configuration interface instance for the module. +// +// ppIdenTokenProviderIf - +// Pointer to variable that will receive pointer to +// IdentityTokenProviderIf instance. +// +// Returns: +// Casa Status +// +// Description: +// Gets identity token provider interface instance. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + IdenTokenProviderIfInstance *pIdenTokenProviderIfInstance; + + DbgTrace(1, "-GetIdenTokenProviderInterface- Start\n", 0); + + // Validate input parameters + if (pModuleConfigIf == NULL + || ppIdenTokenProviderIf == NULL) + { + DbgTrace(0, "-GetIdenTokenProviderInterface- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Make sure that the module has been initialized + if (g_moduleInitialized == false) + { + // The module has not been initialized, synchronize access thought this section + // to avoid having two threads performing initialization. + AcquireModuleMutex; + + // Assume success + retStatus = CASA_STATUS_SUCCESS; + + // Check again in case another thread pre-empted us. + if (g_moduleInitialized == false) + { + // Initialize the IdenTokenIf complex + retStatus = IdenTokenIfInit(); + if (CASA_SUCCESS(retStatus)) + { + // Allocate mutex + if ((g_idenTokenProviderIfMutex = PlatAllocMutex()) != NULL) + { + // Success + g_moduleInitialized = true; + } + else + { + IdenTokenIfUninit(); + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + } + + // Stop synchronization + ReleaseModuleMutex; + + // Exit if we failed + if (g_moduleInitialized == false) + goto exit; + } + + // Allocate space for the interface instance + pIdenTokenProviderIfInstance = malloc(sizeof(*pIdenTokenProviderIfInstance)); + if (pIdenTokenProviderIfInstance) + { + // Initialize the interface instance data + pIdenTokenProviderIfInstance->refCount = 1; + pIdenTokenProviderIfInstance->idenTokenProviderIf.addReference = AddReference; + pIdenTokenProviderIfInstance->idenTokenProviderIf.releaseReference = ReleaseReference; + pIdenTokenProviderIfInstance->idenTokenProviderIf.getIdentityTokenIf = GetIdentityTokenIf; + + // Keep track of this object + PlatAcquireMutex(g_idenTokenProviderIfMutex); + g_numIdenTokenProviderIfObjs ++; + PlatReleaseMutex(g_idenTokenProviderIfMutex); + + // Return the interface to the caller + *ppIdenTokenProviderIf = &pIdenTokenProviderIfInstance->idenTokenProviderIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetIdenTokenProviderInterface- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + +exit: + + DbgTrace(1, "-GetIdenTokenProviderInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/internal.h b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/internal.h new file mode 100644 index 00000000..13b200c9 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/internal.h @@ -0,0 +1,122 @@ +/*********************************************************************** + * + * 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 "iden_token_provider_if.h" +#include "list_entry.h" + +//===[ Type definitions ]================================================== + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +//===[ External prototypes ]=============================================== + +// +// Defined in identoken.c +// + +extern +CasaStatus +GetIdenTokenInterface( + IN const char *pTokenBuf, + IN const int tokenLen, + INOUT IdenTokenIf **ppIdenTokenIf); + +extern +CasaStatus +IdenTokenIfInit(void); + +extern +void +IdenTokenIfUninit(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); + +extern +int +dtoul( + IN char *cp, + IN int len); + +// +// Functions exported by platform.c +// + +extern +HANDLE +PlatAllocMutex(void); + +extern +void +PlatDestroyMutex(HANDLE hMutex); + +extern +void +PlatAcquireMutex(HANDLE hMutex); + +extern +void +PlatReleaseMutex(HANDLE hMutex); + + +//========================================================================= + +#endif // _INTERNAL_H_ + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken.conf b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken.conf new file mode 100644 index 00000000..dec6372d --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken.conf @@ -0,0 +1,15 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# CasaIdentityToken # +# # +# Note: This module is the provider of Casa Identity # +# tokens. # +# # +####################################################### + +LibraryName /opt/novell/CASA/lib/casa_iden_token.so + + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/Makefile.am b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/Makefile.am new file mode 100644 index 00000000..9350ed4d --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/Makefile.am @@ -0,0 +1,114 @@ +####################################################################### +# +# 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 +else +TARGET_CFG = Release +endif + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../../../../.. + +CASAINCLUDE = ../../../../../../CASA/include + +LIBDIR = $(ROOT)/$(LIB) + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +PLATFORMINDEPENDENTSOURCEDIR = .. +PLATFORMDEPENDENTSOURCEDIR = . + +MODULE_NAME = casa_iden_token +MODULE_EXT = so + +CFILES = ../identokenprovider.c \ + ../identoken.c \ + ../util.c \ + platform.c + +CSFILES_CSC := +INCLUDES = -I. -I.. -I../../.. -I$(CASAINCLUDE) -I../../../../../include +RESOURCES = +DEFINES = -Wno-format-extra-args -fno-strict-aliasing +CFLAGS += $(INCLUDES) $(DEFINES) +LIBS = -lpthread -ldl -lexpat +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) + +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/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.c b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.c new file mode 100644 index 00000000..75bafc2b --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.c @@ -0,0 +1,178 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Platform Mutex structure +// +typedef struct _PlatformMutex +{ + pthread_mutex_t mutex; + +} PlatformMutex, *PPlatformMutex; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// Module synchronization mutex +// +pthread_mutex_t g_hModuleMutex = PTHREAD_MUTEX_INITIALIZER; + + +//++======================================================================= +HANDLE +PlatAllocMutex(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + PlatformMutex *pPlatMutex; + pthread_mutexattr_t mutexAttr = {PTHREAD_MUTEX_RECURSIVE}; + + DbgTrace(2, "-PlatAllocMutex- Start\n", 0); + + // Allocate space for our mutex structure + pPlatMutex = malloc(sizeof(*pPlatMutex)); + if (pPlatMutex) + { + // Finish initializing the mutex + pthread_mutex_init(&pPlatMutex->mutex, &mutexAttr); + } + else + { + DbgTrace(0, "-PlatAllocMutex- Memory allocation failure\n", 0); + } + + DbgTrace(2, "-PlatAllocMutex- End, retHandle = %08X\n", (unsigned int) pPlatMutex); + + return (HANDLE) pPlatMutex; +} + + +//++======================================================================= +void +PlatDestroyMutex(HANDLE hMutex) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; + + DbgTrace(2, "-PlatDestroyMutex- Start\n", 0); + + // Free the resources associated with the mutex + pthread_mutex_destroy(&pPlatMutex->mutex); + free(pPlatMutex); + + DbgTrace(2, "-PlatDestroyMutex- End\n", 0); +} + + +//++======================================================================= +void +PlatAcquireMutex(HANDLE hMutex) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; + + DbgTrace(2, "-PlatAcquireMutex- Start\n", 0); + + // Acquire the mutex + pthread_mutex_lock(&pPlatMutex->mutex); + + DbgTrace(2, "-PlatAcquireMutex- End\n", 0); +} + + +//++======================================================================= +void +PlatReleaseMutex(HANDLE hMutex) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; + + DbgTrace(2, "-PlatReleaseMutex- Start\n", 0); + + // Release the mutex + pthread_mutex_unlock(&pPlatMutex->mutex); + + DbgTrace(2, "-PlatRelease- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.h b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.h new file mode 100644 index 00000000..cc32cd17 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.h @@ -0,0 +1,93 @@ +/*********************************************************************** + * + * Copyright (C) 2006 Novell, Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com. + * + * Author: Juan Carlos Luciani + * + ***********************************************************************/ + +#define _GNU_SOURCE + +//===[ Include files ]===================================================== + +#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_IdenToken %s", printBuff); \ + } \ +} +/*#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + openlog("CASA_IdenToken", 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 + + +// +// Module synchronization +// +extern pthread_mutex_t g_hModuleMutex; + +#define AcquireModuleMutex pthread_mutex_lock(&g_hModuleMutex) +#define ReleaseModuleMutex pthread_mutex_unlock(&g_hModuleMutex) + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + +//========================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/util.c b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/util.c new file mode 100644 index 00000000..4e887979 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/idenTokenProviders/casa/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 char *cp, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + 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/native/server/AuthTokenValidate/iden_token_provider_if.h b/CASA-auth-token/native/server/AuthTokenValidate/iden_token_provider_if.h new file mode 100644 index 00000000..9f9a6339 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/iden_token_provider_if.h @@ -0,0 +1,356 @@ +/*********************************************************************** + * + * 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 _IDEN_TOKEN_PROVIDER_IF_H_ +#define _IDEN_TOKEN_PROVIDER_IF_H_ + + +//===[ Include files ]===================================================== + +#include "config_if.h" + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +/************************************************************************** +*************************************************************************** +** ** +** Identity Token Interface Definitions ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +typedef +int +(SSCS_CALL *PFNIdenTokenIf_AddReference)( + IN const void *pIfInstance); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +//=======================================================================-- + + +//++======================================================================= +typedef +void +(SSCS_CALL *PFNIdenTokenIf_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 *PFNIdenTokenIf_GetIdentityId)( + IN const void *pIfInstance, + INOUT char *pIdentIdBuf, + INOUT int *pIdentIdLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pIdentIdBuf - +// Pointer to buffer that will receive the identity id. The returned +// id will be in the form of a NULL terminated string. +// +// pIdentIdBufLen - +// Pointer to variable with the length of the buffer pointed by +// pIdentIdBuf. On exit it contains the length of the returned id +// (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the identity id associated with the identity token. +//=======================================================================-- + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFNIdenTokenIf_GetSourceName)( + IN const void *pIfInstance, + INOUT char *pSourceNameBuf, + INOUT int *pSourceNameLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pSourceNameBuf - +// Pointer to buffer that will receive the name associated with the +// identity information source. The returned name will be in the form +// of a NULL terminated string. +// +// pSourceNameBufLen - +// Pointer to variable with the length of the buffer pointed by +// pSourceNameBuf. On exit it contains the length of the returned +// name (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the name of the identity source associated with the identity token. +//=======================================================================-- + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFNIdenTokenIf_GetSourceUrl)( + IN const void *pIfInstance, + INOUT char *pSourceUrlBuf, + INOUT int *pSourceUrlLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pSourceUrlBuf - +// Pointer to buffer that will receive the URL associated with the +// identity information source. The returned URL will be in the form +// of a NULL terminated string. +// +// pSourceUrlBufLen - +// Pointer to variable with the length of the buffer pointed by +// pSourceUrlBuf. On exit it contains the length of the returned +// URL (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the URL to the identity source associated with the identity token. +//=======================================================================-- + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFNIdenTokenIf_AttributeEnumerate)( + IN const void *pIfInstance, + INOUT int *pEnumHandle, + INOUT char *pAttribNameBuf, + INOUT int *pAttribNameLen, + INOUT char *pAttribValueBuf, + INOUT int *pAttribValueLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pEnumHandle - +// Pointer to enumeration handle. Must be set to 0 to start an +// enumeration. Note the enumeration handle advances if the +// function returns success. +// +// pAttribNameBuf - +// Pointer to buffer that will receive the identity attribute name. The +// returned name will be in the form of a NULL terminated string. +// +// pAttribNameLen - +// Pointer to variable with the length of the buffer pointed by +// pAttribNameBuf. On exit it contains the length of the returned +// name (including the NULL terminator). +// +// pAttribValueBuf - +// Pointer to buffer that will receive the identity attribute value. The +// returned value will be in the form of a NULL terminated string. +// +// pAttribValueLen - +// Pointer to variable with the length of the buffer pointed by +// pAttribValueBuf. On exit it contains the length of the returned +// value (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Enumerates through the attributes associated with the identity token. +//=======================================================================-- + + +// +// Identity Token Interface Object +// +typedef struct _IdenTokenIf +{ + PFNIdenTokenIf_AddReference addReference; + PFNIdenTokenIf_ReleaseReference releaseReference; + PFNIdenTokenIf_GetIdentityId getIdentityId; + PFNIdenTokenIf_GetSourceName getSourceName; + PFNIdenTokenIf_GetSourceUrl getSourceUrl; + PFNIdenTokenIf_AttributeEnumerate attributeEnumerate; + +} IdenTokenIf, *PIdenTokenIf; + + +/************************************************************************** +*************************************************************************** +** ** +** Identity Token Provider Interface Definitions ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +typedef +int +(SSCS_CALL *PFNIdenTokenProviderIf_AddReference)( + IN const void *pIfInstance); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +//=======================================================================-- + + +//++======================================================================= +typedef +void +(SSCS_CALL *PFNIdenTokenProviderIf_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 *PFNIdenTokenProviderIf_GetIdentityTokenIf)( + IN const void *pIfInstance, + IN const char *pTokenBuf, + IN const int tokenLen, + INOUT IdenTokenIf **ppIdenTokenIf); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pTokenBuf - +// Pointer to null terminated string containing an identity token. +// +// tokenLen - +// Length of the token contained in the token buffer. +// +// ppIdenTokenIf - +// Pointer to variable that will receive pointer to identity +// token interface. +// +// Returns: +// Casa Status +// +// Description: +// Get identity token interface instance for the specified token. +//=======================================================================-- + + +// +// Identity Token Provider Interface Object +// +typedef struct _IdenTokenProviderIf +{ + PFNIdenTokenProviderIf_AddReference addReference; + PFNIdenTokenProviderIf_ReleaseReference releaseReference; + PFNIdenTokenProviderIf_GetIdentityTokenIf getIdentityTokenIf; + +} IdenTokenProviderIf, *PIdenTokenProviderIf; + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFN_GetIdenTokenProviderIfRtn)( + IN const ConfigIf *pModuleConfigIf, + INOUT IdenTokenProviderIf **ppIdenTokenProviderIf); +// +// Arguments: +// pModuleConfigIf - +// Pointer to configuration interface instance for the module. +// +// ppIdenTokenProviderIf - +// Pointer to variable that will receive pointer to +// IdentityTokenProviderIf instance. +// +// Returns: +// Casa Status +// +// Description: +// Gets identity token provider interface instance. +//=======================================================================-- + +#define GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN_SYMBOL "GetIdenTokenProviderInterface" +#define GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN GetIdenTokenProviderInterface + + +#endif // #ifndef _IDEN_TOKEN_PROVIDER_IF_H_ + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/identoken.c b/CASA-auth-token/native/server/AuthTokenValidate/identoken.c new file mode 100644 index 00000000..f9ff26d9 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/identoken.c @@ -0,0 +1,320 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Identity Token Module definition +// +typedef struct _IdenTokenProviderModule +{ + LIST_ENTRY listEntry; + char *pTypeName; + int typeNameLen; + LIB_HANDLE libHandle; + IdenTokenProviderIf *pIdenTokenProviderIf; + +} IdenTokenProviderModule, *PIdenTokenProviderModule; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// IdenTokenProviderModule list and syncronization mutex +// +static +LIST_ENTRY g_IdenTokenProviderModuleListHead = {&g_IdenTokenProviderModuleListHead, &g_IdenTokenProviderModuleListHead}; + +static +HANDLE g_idenTokenMutex = NULL; + + +//++======================================================================= +CasaStatus +GetIdenTokenProviderInterface( + IN const char *pIdenTokenTypeName, + INOUT IdenTokenProviderIf **ppIdenTokenProviderIf) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + ConfigIf *pModuleConfigIf; + + DbgTrace(2, "-GetIdenTokenProviderInterface- Start\n", 0); + + // Get the configuration for the module + retStatus = GetConfigInterface("/etc/opt/novell/CASA/authtoken.d/modules.d", + pIdenTokenTypeName, + &pModuleConfigIf); + if (CASA_SUCCESS(retStatus) + && CasaStatusCode(retStatus) != CASA_STATUS_OBJECT_NOT_FOUND) + { + LIST_ENTRY *pListEntry; + IdenTokenProviderModule *pIdenTokenProviderModule = NULL; + int32_t idenTokenTypeNameLen = strlen(pIdenTokenTypeName); + + // Gain exclusive access to our mutex + PlatAcquireMutex(g_idenTokenMutex); + + // Look if we already have the module in our list + pListEntry = g_IdenTokenProviderModuleListHead.Flink; + while (pListEntry != &g_IdenTokenProviderModuleListHead) + { + // Get pointer to the current entry + pIdenTokenProviderModule = CONTAINING_RECORD(pListEntry, IdenTokenProviderModule, listEntry); + + // Check if this is the module that we need + if (pIdenTokenProviderModule->typeNameLen == idenTokenTypeNameLen + && memcmp(pIdenTokenTypeName, pIdenTokenProviderModule->pTypeName, idenTokenTypeNameLen) == 0) + { + // This is the module that we need, stop looking. + break; + } + else + { + // This is not the module that we are looking for + pIdenTokenProviderModule = NULL; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Proceed based on whether or not a module was found + if (pIdenTokenProviderModule) + { + // Module found in our list, provide the caller with its IdenTokenProviderIf + // instance after we have incremented its reference count. + pIdenTokenProviderModule->pIdenTokenProviderIf->addReference(pIdenTokenProviderModule->pIdenTokenProviderIf); + *ppIdenTokenProviderIf = pIdenTokenProviderModule->pIdenTokenProviderIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + // Needed module not found in our list, create an entry. + pIdenTokenProviderModule = malloc(sizeof(*pIdenTokenProviderModule)); + if (pIdenTokenProviderModule) + { + // Allocate buffer to contain the authentication type name within the module entry + pIdenTokenProviderModule->pTypeName = malloc(idenTokenTypeNameLen + 1); + if (pIdenTokenProviderModule->pTypeName) + { + char *pLibraryName; + + // Initialize the library handle field + pIdenTokenProviderModule->libHandle = NULL; + + // Save the auth type name within the entry + strcpy(pIdenTokenProviderModule->pTypeName, pIdenTokenTypeName); + pIdenTokenProviderModule->typeNameLen = idenTokenTypeNameLen; + + // Obtain the name of the library that we must load + pLibraryName = pModuleConfigIf->getEntryValue(pModuleConfigIf, "LibraryName"); + if (pLibraryName) + { + // Load the library + pIdenTokenProviderModule->libHandle = OpenLibrary(pLibraryName); + if (pIdenTokenProviderModule->libHandle) + { + PFN_GetIdenTokenProviderIfRtn pGetIdenTokenProviderIfRtn; + + // Library has been loaded, now get a pointer to its GetIdenTokenProviderProviderInterface routine + pGetIdenTokenProviderIfRtn = (PFN_GetIdenTokenProviderIfRtn) GetFunctionPtr(pIdenTokenProviderModule->libHandle, + GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN_SYMBOL); + if (pGetIdenTokenProviderIfRtn) + { + // Now, obtain the modules IdenTokenProviderIf. + retStatus = (pGetIdenTokenProviderIfRtn)(pModuleConfigIf, &pIdenTokenProviderModule->pIdenTokenProviderIf); + } + else + { + DbgTrace(0, "-GetIdenTokenProviderInterface- GetFunctionPtr error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_LIBRARY_LOAD_FAILURE); + } + } + else + { + DbgTrace(0, "-GetIdenTokenProviderInterface- OpenLibrary error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_LIBRARY_LOAD_FAILURE); + } + + // Free the buffer holding the library name + free(pLibraryName); + } + else + { + DbgTrace(0, "-GetIdenTokenProviderInterface- 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 IdenTokenProviderIf instance for the + // module. + if (CASA_SUCCESS(retStatus)) + { + // Insert the entry in the list, provide the caller with its IdenTokenProviderIf + // instance after we have incremented its reference count. + InsertTailList(&g_IdenTokenProviderModuleListHead, &pIdenTokenProviderModule->listEntry); + pIdenTokenProviderModule->pIdenTokenProviderIf->addReference(pIdenTokenProviderModule->pIdenTokenProviderIf); + *ppIdenTokenProviderIf = pIdenTokenProviderModule->pIdenTokenProviderIf; + } + else + { + // Failed, free resources. + free(pIdenTokenProviderModule->pTypeName); + if (pIdenTokenProviderModule->libHandle) + CloseLibrary(pIdenTokenProviderModule->libHandle); + free(pIdenTokenProviderModule); + } + } + else + { + DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to allocate buffer\n", 0); + + // Free buffer allocated for entry + free(pIdenTokenProviderModule); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to allocate buffer\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + // Release exclusive access to our mutex + PlatReleaseMutex(g_idenTokenMutex); + + // Release config interface instance + pModuleConfigIf->releaseReference(pModuleConfigIf); + } + else + { + DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to obtain config interface\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_CONFIGURATION_ERROR); + } + + DbgTrace(2, "-GetIdenTokenProviderInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +IdenTokenInit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Initializes the identity token complex. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + + DbgTrace(1, "-IdenTokenInit- Start\n", 0); + + // Allocate mutex + if ((g_idenTokenMutex = PlatAllocMutex()) != NULL) + retStatus = CASA_STATUS_SUCCESS; + else + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + + DbgTrace(1, "-IdenTokenInit- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +IdenTokenUninit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Uninitializes the indentity token complex. +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-IdenTokenUninit- Start\n", 0); + + // Free mutex if necessary + if (g_idenTokenMutex) + { + PlatDestroyMutex(g_idenTokenMutex); + g_idenTokenMutex = NULL; + } + + DbgTrace(1, "-IdenTokenUninit- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/internal.h b/CASA-auth-token/native/server/AuthTokenValidate/internal.h new file mode 100644 index 00000000..eff9cc93 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/internal.h @@ -0,0 +1,222 @@ +/*********************************************************************** + * + * 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 "proto.h" +#include "list_entry.h" +#include "config_if.h" +#include "iden_token_provider_if.h" + +//===[ Type definitions ]================================================== + +// +// Authentication Token structure +// +typedef struct _AuthToken +{ + int tokenLifetime; + char *pSignature; + int signatureLen; + char *pIdenTokenType; + int idenTokenTypeLen; + char *pIdenToken; + int idenTokenLen; + +} AuthToken, *PAuthToken; + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +//===[ External prototypes ]=============================================== + +// +// Functions exported by config.c +// +extern +CasaStatus +GetConfigInterface( + IN const char *pConfigFolder, + IN const char *pConfigName, + INOUT ConfigIf **ppConfigIf); + +extern +CasaStatus +ConfigIfInit(void); + +extern +void +ConfigIfUninit(void); + +// +// Functions exported by identoken.c +// +extern +CasaStatus +GetIdenTokenProviderInterface( + IN const char *pIdenTokenTypeName, + INOUT IdenTokenProviderIf **ppIdenTokenProviderIf); + +extern +CasaStatus +IdenTokenInit(void); + +extern +void +IdenTokenUninit(void); + +// +// Functions exported by platform.c +// +extern +HANDLE +PlatAllocMutex(void); + +extern +void +PlatDestroyMutex(HANDLE hMutex); + +extern +void +PlatAcquireMutex(HANDLE hMutex); + +extern +void +PlatReleaseMutex(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); + +// +// Functions exported by principal.c +// + +extern +CasaStatus +GetPrincipalInterface( + IN IdenTokenIf *pIdenTokenIf, + INOUT PrincipalIf **ppPrincipalIf); + +extern +CasaStatus +PrincipalIfInit(void); + +extern +void +PrincipalIfUninit(void); + +// +// Functions exported by validate.c +// + +extern +CasaStatus SSCS_CALL +ValidateAuthToken( + IN const char *pServiceName, + IN const char *pTokenBuf, + IN const int tokenBufLen, + INOUT PrincipalIf **ppPrincipalIf); + +// +// Functions exported by authtoken.c +// + +extern +CasaStatus +CreateAuthToken( + IN char *pTokenBuf, + IN int tokenBufLen, + INOUT AuthToken **ppAuthToken); + +extern +void +RelAuthToken( + IN AuthToken *pAuthToken); + +extern +CasaStatus +CheckAuthToken( + IN AuthToken *pAuthToken, + IN const char *pServiceName); + +// +// 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); + +extern +int +dtoul( + IN char *cp, + IN int len); + + +//========================================================================= + +#endif // _INTERNAL_H_ + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/linux/Makefile.am b/CASA-auth-token/native/server/AuthTokenValidate/linux/Makefile.am new file mode 100644 index 00000000..6811ab26 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/linux/Makefile.am @@ -0,0 +1,116 @@ +####################################################################### +# +# 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 +else +TARGET_CFG = Release +endif + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../../.. +CASAINCLUDE = ../../../../CASA/include + +LIBDIR = $(ROOT)/$(LIB) + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +PLATFORMINDEPENDENTSOURCEDIR = .. +PLATFORMDEPENDENTSOURCEDIR = . + +MODULE_NAME = libcasa_s_authtoken +MODULE_EXT = so + +CFILES = ../config.c \ + ../authtoken.c \ + ../principal.c \ + ../util.c \ + ../validate.c \ + ../identoken.c \ + platform.c + +CSFILES_CSC := +INCLUDES = -I. -I.. -I$(CASAINCLUDE) -I../../../include +RESOURCES = +DEFINES = -Wno-format-extra-args -fno-strict-aliasing +CFLAGS += $(INCLUDES) $(DEFINES) +LIBS = -lpthread -ldl -lexpat +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) + +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/native/server/AuthTokenValidate/linux/platform.c b/CASA-auth-token/native/server/AuthTokenValidate/linux/platform.c new file mode 100644 index 00000000..d24762b8 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/linux/platform.c @@ -0,0 +1,268 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Platform Mutex structure +// +typedef struct _PlatformMutex +{ + pthread_mutex_t mutex; + +} PlatformMutex, *PPlatformMutex; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// Module synchronization mutex +// +pthread_mutex_t g_hModuleMutex = PTHREAD_MUTEX_INITIALIZER; + + +//++======================================================================= +HANDLE +PlatAllocMutex(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + PlatformMutex *pPlatMutex; + pthread_mutexattr_t mutexAttr = {PTHREAD_MUTEX_RECURSIVE}; + + DbgTrace(2, "-PlatAllocMutex- Start\n", 0); + + // Allocate space for our mutex structure + pPlatMutex = malloc(sizeof(*pPlatMutex)); + if (pPlatMutex) + { + // Finish initializing the mutex + pthread_mutex_init(&pPlatMutex->mutex, &mutexAttr); + } + else + { + DbgTrace(0, "-PlatAllocMutex- Memory allocation failure\n", 0); + } + + DbgTrace(2, "-PlatAllocMutex- End, retHandle = %08X\n", (unsigned int) pPlatMutex); + + return (HANDLE) pPlatMutex; +} + + +//++======================================================================= +void +PlatDestroyMutex(HANDLE hMutex) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; + + DbgTrace(2, "-PlatDestroyMutex- Start\n", 0); + + // Free the resources associated with the mutex + pthread_mutex_destroy(&pPlatMutex->mutex); + free(pPlatMutex); + + DbgTrace(2, "-PlatDestroyMutex- End\n", 0); +} + + +//++======================================================================= +void +PlatAcquireMutex(HANDLE hMutex) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; + + DbgTrace(2, "-PlatAcquireMutex- Start\n", 0); + + // Acquire the mutex + pthread_mutex_lock(&pPlatMutex->mutex); + + DbgTrace(2, "-PlatAcquireMutex- End\n", 0); +} + + +//++======================================================================= +void +PlatReleaseMutex(HANDLE hMutex) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex; + + DbgTrace(2, "-PlatReleaseMutex- Start\n", 0); + + // Release the mutex + pthread_mutex_unlock(&pPlatMutex->mutex); + + DbgTrace(2, "-PlatRelease- 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 = %d\n", dlerror()); + } + + 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); + + 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 = %d\n", dlerror()); + } + + DbgTrace(1, "-GetFunctionPtr- End, pFuncPtr = %08X\n", pFuncPtr); + + return pFuncPtr; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/linux/platform.h b/CASA-auth-token/native/server/AuthTokenValidate/linux/platform.h new file mode 100644 index 00000000..447efe82 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/linux/platform.h @@ -0,0 +1,100 @@ +/*********************************************************************** + * + * 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 + +//===[ 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_AuthTokenValidate %s", printBuff); \ + } \ +} +/*#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0 || DebugLevel >= LEVEL) \ + { \ + openlog("CASA_AuthTokenValidate", 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 + +// +// Module synchronization +// +extern pthread_mutex_t g_hModuleMutex; + +#define AcquireModuleMutex pthread_mutex_lock(&g_hModuleMutex) +#define ReleaseModuleMutex pthread_mutex_unlock(&g_hModuleMutex) + +// +// Other definitions +// +#define LIB_HANDLE void* + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + +//========================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/principal.c b/CASA-auth-token/native/server/AuthTokenValidate/principal.c new file mode 100644 index 00000000..e4361731 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/principal.c @@ -0,0 +1,482 @@ +/*********************************************************************** + * + * 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 Interface instance data +// +typedef struct _PrincipalIfInstance +{ + int refCount; + IdenTokenIf *pIdenTokenIf; + PrincipalIf principalIf; + +} PrincipalIfInstance, *PPrincipalIfInstance; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// PrincipalIf variables +static +int g_numPrincipalIfObjs = 0; + +// Synchronization mutex +static +HANDLE g_principalIfMutex = NULL; + + +//++======================================================================= +static +int SSCS_CALL +AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf); + + DbgTrace(2, "-AddReference- Start\n", 0); + + // Increment the reference count on the object + PlatAcquireMutex(g_principalIfMutex); + pPrincipalIfInstance->refCount ++; + refCount = pPrincipalIfInstance->refCount; + PlatReleaseMutex(g_principalIfMutex); + + DbgTrace(2, "-AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +static +void SSCS_CALL +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; + PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf); + + DbgTrace(2, "-ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + PlatAcquireMutex(g_principalIfMutex); + pPrincipalIfInstance->refCount --; + if (pPrincipalIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numPrincipalIfObjs --; + } + PlatReleaseMutex(g_principalIfMutex); + + // Free object if necessary + if (freeObj) + { + // Release the identity token interface associated with our instance + pPrincipalIfInstance->pIdenTokenIf->releaseReference(pPrincipalIfInstance->pIdenTokenIf); + + // Free our instance data + free(pPrincipalIfInstance); + } + + DbgTrace(2, "-ReleaseReference- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus SSCS_CALL +GetIdentityId( + IN const void *pIfInstance, + INOUT char *pIdentIdBuf, + INOUT int *pIdentIdLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pIdentIdBuf - +// Pointer to buffer that will receive the identity id. The returned +// id will be in the form of a NULL terminated string. +// +// pIdentIdBufLen - +// Pointer to variable with the length of the buffer pointed by +// pIdentIdBuf. On exit it contains the length of the returned id +// (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the identity id associated with the identity token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf); + + DbgTrace(2, "-GetIdentityId- Start\n", 0); + + // Just call into the identity token + retStatus = pPrincipalIfInstance->pIdenTokenIf->getIdentityId(pPrincipalIfInstance->pIdenTokenIf, + pIdentIdBuf, + pIdentIdLen); + + DbgTrace(2, "-GetIdentityId- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus SSCS_CALL +GetSourceName( + IN const void *pIfInstance, + INOUT char *pSourceNameBuf, + INOUT int *pSourceNameLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pSourceNameBuf - +// Pointer to buffer that will receive the name associated with the +// identity information source. The returned name will be in the form +// of a NULL terminated string. +// +// pSourceNameBufLen - +// Pointer to variable with the length of the buffer pointed by +// pSourceNameBuf. On exit it contains the length of the returned +// name (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the name of the identity source associated with the identity token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf); + + DbgTrace(2, "-GetSourceName- Start\n", 0); + + // Just call into the identity token + retStatus = pPrincipalIfInstance->pIdenTokenIf->getSourceName(pPrincipalIfInstance->pIdenTokenIf, + pSourceNameBuf, + pSourceNameLen); + + DbgTrace(2, "-GetSourceName- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus SSCS_CALL +GetSourceUrl( + IN const void *pIfInstance, + INOUT char *pSourceUrlBuf, + INOUT int *pSourceUrlLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pSourceUrlBuf - +// Pointer to buffer that will receive the URL associated with the +// identity information source. The returned URL will be in the form +// of a NULL terminated string. +// +// pSourceUrlBufLen - +// Pointer to variable with the length of the buffer pointed by +// pSourceUrlBuf. On exit it contains the length of the returned +// URL (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Get the URL to the identity source associated with the identity token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf); + + DbgTrace(2, "-GetSourceUrl- Start\n", 0); + + // Just call into the identity token + retStatus = pPrincipalIfInstance->pIdenTokenIf->getSourceUrl(pPrincipalIfInstance->pIdenTokenIf, + pSourceUrlBuf, + pSourceUrlLen); + + DbgTrace(2, "-GetSourceUrl- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus SSCS_CALL +AttributeEnumerate( + IN const void *pIfInstance, + INOUT int *pEnumHandle, + INOUT char *pAttribNameBuf, + INOUT int *pAttribNameLen, + INOUT char *pAttribValueBuf, + INOUT int *pAttribValueLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pEnumHandle - +// Pointer to enumeration handle. Must be set to 0 to start an +// enumeration. +// +// pAttribNameBuf - +// Pointer to buffer that will receive the identity attribute name. The +// returned name will be in the form of a NULL terminated string. +// +// pAttribNameLen - +// Pointer to variable with the length of the buffer pointed by +// pAttribNameBuf. On exit it contains the length of the returned +// name (including the NULL terminator). +// +// pAttribValueBuf - +// Pointer to buffer that will receive the identity attribute value. The +// returned value will be in the form of a NULL terminated string. +// +// pAttribValueLen - +// Pointer to variable with the length of the buffer pointed by +// pAttribValueBuf. On exit it contains the length of the returned +// value (including the NULL terminator). +// +// +// Returns: +// Casa Status +// +// Description: +// Enumerates through the attributes associated with the identity token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf); + + DbgTrace(2, "-AttributeEnumerate- Start\n", 0); + + // Just call into the identity token + retStatus = pPrincipalIfInstance->pIdenTokenIf->attributeEnumerate(pPrincipalIfInstance->pIdenTokenIf, + pEnumHandle, + pAttribNameBuf, + pAttribNameLen, + pAttribValueBuf, + pAttribValueLen); + + DbgTrace(2, "-AttributeEnumerate- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +GetPrincipalInterface( + IN IdenTokenIf *pIdenTokenIf, + INOUT PrincipalIf **ppPrincipalIf) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Get principal interface instanced for the identity associated +// with specified identity token. +// +// L2 +//=======================================================================-- +{ + PrincipalIfInstance *pPrincipalIfInstance; + CasaStatus retStatus; + + DbgTrace(2, "-GetPrincipalInterface- Start\n", 0); + + // Create a PrincipalIfInstance object for it. + pPrincipalIfInstance = malloc(sizeof(*pPrincipalIfInstance)); + if (pPrincipalIfInstance) + { + // Initialize the PrincipalIf within the instance data + pPrincipalIfInstance->principalIf.addReference = AddReference; + pPrincipalIfInstance->principalIf.releaseReference = ReleaseReference; + pPrincipalIfInstance->principalIf.getIdentityId = GetIdentityId; + pPrincipalIfInstance->principalIf.getSourceName = GetSourceName; + pPrincipalIfInstance->principalIf.getSourceUrl = GetSourceUrl; + pPrincipalIfInstance->principalIf.attributeEnumerate = AttributeEnumerate; + + // Keep reference to the identity token interface instance + pPrincipalIfInstance->pIdenTokenIf = pIdenTokenIf; + pIdenTokenIf->addReference(pIdenTokenIf); + + // Return the PrincipalIf associated with the instance data after + // incrementing its reference count. + pPrincipalIfInstance->refCount ++; + *ppPrincipalIf = &pPrincipalIfInstance->principalIf; + + // Bump up our interface instance count + PlatAcquireMutex(g_principalIfMutex); + g_numPrincipalIfObjs ++; + PlatReleaseMutex(g_principalIfMutex); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetPrincipalInterface- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(2, "-GetPrincipalInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +PrincipalIfInit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Initializes the principal interface complex. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + + DbgTrace(1, "-PrincipalIfInit- Start\n", 0); + + // Allocate mutex + if ((g_principalIfMutex = PlatAllocMutex()) != NULL) + retStatus = CASA_STATUS_SUCCESS; + else + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + + DbgTrace(1, "-PrincipalIfInit- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +PrincipalIfUninit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Uninitializes the configuration interface complex. +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-PrincipalIfUninit- Start\n", 0); + + // Free mutex if necessary + if (g_principalIfMutex) + { + PlatDestroyMutex(g_principalIfMutex); + g_principalIfMutex = NULL; + } + + DbgTrace(1, "-PrincipalIfUninit- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/server/AuthTokenValidate/util.c b/CASA-auth-token/native/server/AuthTokenValidate/util.c new file mode 100644 index 00000000..bf6a48b6 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/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 char *cp, + IN 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/native/server/AuthTokenValidate/validate.c b/CASA-auth-token/native/server/AuthTokenValidate/validate.c new file mode 100644 index 00000000..24c9dcb7 --- /dev/null +++ b/CASA-auth-token/native/server/AuthTokenValidate/validate.c @@ -0,0 +1,244 @@ +/*********************************************************************** + * + * 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; + +// +// Initialization variables +// +static +bool g_moduleInitialized = false; + + +//++======================================================================= +CasaStatus SSCS_CALL +ValidateAuthToken( + IN const char *pServiceName, + IN const char *pTokenBuf, + IN const int tokenBufLen, + INOUT PrincipalIf **ppPrincipalIf) +// +// Arguments: +// pServiceName - +// Pointer to NULL terminated string that contains the +// name of the service targeted by the token. +// +// 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. +// +// tokenBufLen - +// Length of the data contained within the buffer pointed +// at by pTokenBuf. +// +// ppPrincipalIf - +// Pointer to variable that will receive a pointer to a principal +// interface with information about the authenticated entity. +// IMPORTANT NOTE: The caller is responsible for releasing the +// interface after it is done with it to avoid a resource leak. +// +// Returns: +// Casa status. +// +// Description: +// Validates authentication token. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + char *pDecodedTokenBuf; + int decodedTokenBufLen; + PrincipalIf *pPrincipalIf; + + DbgTrace(1, "-ValidateAuthToken- Start\n", 0); + + // Validate input parameters + if (pServiceName == NULL + || pTokenBuf == NULL + || tokenBufLen == 0 + || ppPrincipalIf == NULL) + { + DbgTrace(0, "-ValidateAuthToken- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Make sure that the module has been initialized + if (g_moduleInitialized == false) + { + // The module has not been initialized, synchronize access thought this section + // to avoid having two threads performing initialization. + AcquireModuleMutex; + + // Assume success + retStatus = CASA_STATUS_SUCCESS; + + // Check again in case another thread pre-empted us. + if (g_moduleInitialized == false) + { + // Initialize the ConfigIf complex + retStatus = ConfigIfInit(); + if (CASA_SUCCESS(retStatus)) + { + // Initialize the PrincipalIf complex + retStatus = PrincipalIfInit(); + if (CASA_SUCCESS(retStatus)) + { + // Initialize the IdenToken complex + retStatus = IdenTokenInit(); + if (CASA_SUCCESS(retStatus)) + { + // Success + g_moduleInitialized = true; + } + else + { + PrincipalIfUninit(); + ConfigIfUninit(); + } + } + else + { + ConfigIfUninit(); + } + } + } + + // Stop synchronization + ReleaseModuleMutex; + + // Exit if we failed + if (g_moduleInitialized == false) + goto exit; + } + + // First decode the token string + retStatus = DecodeData(pTokenBuf, + tokenBufLen, + (void**) &pDecodedTokenBuf, + &decodedTokenBufLen); + if (CASA_SUCCESS(retStatus)) + { + AuthToken *pAuthToken; + + // Token was decoded successfully, now create an authentication token object with it. + retStatus = CreateAuthToken(pDecodedTokenBuf, decodedTokenBufLen, &pAuthToken); + if (CASA_SUCCESS(retStatus)) + { + // Now check the validity of the token + retStatus = CheckAuthToken(pAuthToken, pServiceName); + if (CASA_SUCCESS(retStatus)) + { + IdenTokenProviderIf *pIdenTokenProviderIf; + + // The token was validated, now + // Obtain Identity Token Provider interface + retStatus = GetIdenTokenProviderInterface(pAuthToken->pIdenTokenType, + &pIdenTokenProviderIf); + if (CASA_SUCCESS(retStatus)) + { + IdenTokenIf *pIdenTokenIf; + + // Use the Identity Token Provider to get an Identity Token Interface instance + retStatus = pIdenTokenProviderIf->getIdentityTokenIf(pIdenTokenProviderIf, + pAuthToken->pIdenToken, + pAuthToken->idenTokenLen, + &pIdenTokenIf); + if (CASA_SUCCESS(retStatus)) + { + // Now create a principal interface instance with the identity information present in + // the identity token. + retStatus = GetPrincipalInterface(pIdenTokenIf, &pPrincipalIf); + if (CASA_SUCCESS(retStatus)) + { + // Success, return the principal interface to the caller. + *ppPrincipalIf = pPrincipalIf; + } + else + { + DbgTrace(0, "-ValidateAuthToken- Failed to instantiate principal interface\n", 0); + } + + // Release identity token interface + pIdenTokenIf->releaseReference(pIdenTokenIf); + } + else + { + DbgTrace(0, "-ValidateAuthToken- Failed to instantiate identity token\n", 0); + } + + // Release identity token provider interface + pIdenTokenProviderIf->releaseReference(pIdenTokenProviderIf); + } + else + { + DbgTrace(0, "-ValidateAuthToken- Failed to obtain identity token provider interface\n", 0); + } + } + + // Free the AuthToken object + RelAuthToken(pAuthToken); + } + else + { + DbgTrace(0, "-ValidateAuthToken- Failed to create authentication token object\n", 0); + } + + // Free the decoded token buffer + free(pDecodedTokenBuf); + } + else + { + DbgTrace(0, "-ValidateAuthToken- Token decode failure\n", 0); + } + +exit: + + DbgTrace(1, "-ValidateAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/native/server/Makefile.am b/CASA-auth-token/native/server/Makefile.am new file mode 100644 index 00000000..9bc6e8c3 --- /dev/null +++ b/CASA-auth-token/native/server/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 = AuthTokenValidate ApacheSupport PamSupport + +DIST_SUBDIRS = AuthTokenValidate ApacheSupport PamSupport + +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/native/server/PamSupport/Makefile.am b/CASA-auth-token/native/server/PamSupport/Makefile.am new file mode 100644 index 00000000..6184e626 --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/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 + +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/native/server/PamSupport/README b/CASA-auth-token/native/server/PamSupport/README new file mode 100644 index 00000000..3996c09d --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/README @@ -0,0 +1,80 @@ +/*********************************************************************** + * + * README for pam_casaauthtok + * + ***********************************************************************/ + +INTRODUCTION + +pam_casaauthtok is a PAM authentication module which can be configured +to validate credentials consisting of CASA Authentication Tokens. + +CONFIGURATION + +To use pam_casaauthtok as a PAM authentication module for your service, +add the following line to the service's PAM configuration file: + +auth required pam_casaauthtok.so + +pam_casaauthtok supports the following input parameters: + +U - This parameter tells pam_casaauthtok that it must verify that + the username is set to "CasaPrincipal". If the parameter is not + specified then pam_casaauthtok does not check the username. + +CLIENT PROGRAMMING NOTES + +Clients must specify the same service name when requesting Authentication +Tokens from the CASA Client as the service name specified by the server +when opening a PAM handle. + +SERVER PROGRAMMING NOTES + +Server applications validating credentials containing CASA Authentication +tokens can obtain the following information about the authenticated identity: + +username - This is obtained by querying PAM using the pam_get_item() call with +the item type set to PAM_USER. This can also be obtained by querying PAM +using the pam_getenv() call with the variable name set to "IdentityId". The +username is the user's unique id within the authentication realm. When the +authentication realm is an LDAP database, the username consists of the user's fdn. +Note that PAM applications using pam_casaauthtok need to set username to +"CasaPrincipal" when opening a PAM handle and then the variable is updated by +pam_casaauthtok during the authentication process with the identity information +of the authenticated entity. + +Name of the source of identity data (Authentication Realm) - This is obtained +by querying PAM using the pam_getenv() call with the variable name set to +"IdentityDataSourceName". + +URL to the source of identity data - This is obtained +by querying PAM using the pam_getenv() call with the variable name set to +"IdentityDataSourceUrl". + +Attributes of the authenticated identity - The attributes are set as environment +variables associated with the PAM handle. The environment variable names match +the names of the attributes. The attributes associated with the authenticated +identity and expressed as environment variables are configured at the time that +the service is enabled for CASA Authentication. + +EXAMPLE SERVER APPLICATION + +See test/test.c for an example application using PAM to authenticate credentials +consisting of CASA Authentication Tokens. + +SECURITY CONSIDERATIONS + +CASA Authenticatication Tokens when compromised can be used to either impersonate +a user or to obtain identity information about the user. Because of this it is +important that the tokens be secured by applications making use of them. It is +recommended that the tokens be transmitted using SSL. + + + + + + + + + + diff --git a/CASA-auth-token/native/server/PamSupport/TODO b/CASA-auth-token/native/server/PamSupport/TODO new file mode 100644 index 00000000..90fb8aeb --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/TODO @@ -0,0 +1,13 @@ +/*********************************************************************** + * + * TODO for pam_casaauthtok + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for pam_casaauthtok. + +OUTSTANDING ITEMS + +None. diff --git a/CASA-auth-token/native/server/PamSupport/linux/Makefile.am b/CASA-auth-token/native/server/PamSupport/linux/Makefile.am new file mode 100644 index 00000000..6d9685b9 --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/linux/Makefile.am @@ -0,0 +1,112 @@ +####################################################################### +# +# 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 +else +TARGET_CFG = Release +endif + +SUBDIRS = + +DIST_SUBDIRS = + +ROOT = ../../.. + +CASAINCLUDE = ../../../../CASA/include + +LIBDIR = $(ROOT)/$(LIB) + +# handle Mono secondary dependencies +export MONO_PATH := $(MONO_PATH) + +PLATFORMINDEPENDENTSOURCEDIR = .. +PLATFORMDEPENDENTSOURCEDIR = . + +MODULE_NAME = pam_casaauthtok +MODULE_EXT = so + +CFILES = ../pam_authtoken.c + +CSFILES_CSC := +INCLUDES = -I. -I$(CASAINCLUDE) -I../../../include +RESOURCES = +DEFINES = -Wno-format-extra-args -fno-strict-aliasing + +CFLAGS += $(INCLUDES) $(DEFINES) +LIBS = -lpthread -lpam -lcasa_s_authtoken +LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(LIBDIR)/$(TARGET_CFG) + +OBJDIR = ./$(TARGET_CFG)/$(LIB) +OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) + +EXTRA_DIST = $(CFILES) + +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: +#cd $(TARGET_CFG); rm -rf *.dbg *.exe *.dll *.o *.so; cd ..; rmdir $(OBJDIR) + rm -rf $(TARGET_CFG) + +distclean-local: + +maintainer-clean-local: + rm -f Makefile.in + diff --git a/CASA-auth-token/native/server/PamSupport/pam_authtoken.c b/CASA-auth-token/native/server/PamSupport/pam_authtoken.c new file mode 100644 index 00000000..44f2b296 --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/pam_authtoken.c @@ -0,0 +1,649 @@ +/*********************************************************************** + * + * 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 +#include +#include + +#ifndef LINUX +#include +#endif + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#define PAM_SM_PASSWORD +#define PAM_SM_SESSION + +#include +#include + +#include + +// +// Environment variables set by module +// +static char CasaIdentityIdEnvVar[] = "IdentityId= "; +static char CasaIdentitySourceNameEnvVar[] = "IdentityDataSourceName= "; +static char CasaIdentitySourceUrlEnvVar[] = "IdentityDataSourceUrl= "; + + +/* ************************************************************************ + * LogError() + * + * Logs error to syslog. + * + * L2 + * ************************************************************************/ +static void +LogError(char *pFormatStr, ... ) +{ + va_list args; + + openlog("pam_casaauthtok", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER); + va_start(args, pFormatStr); + vsyslog(LOG_USER | LOG_INFO, pFormatStr, args); + va_end(args); + closelog(); +} + + +/* ************************************************************************ + * pam_sm_authenticate() + * + * Service provider implementation for pam_authenticate(). + * + * This is a PAM authentication management function. + * + * We are going to validate the credentials using the CASA Authentication + * Token Credential APIs. + * + * L2 + * ************************************************************************/ +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + int retStatus = PAM_SUCCESS; + bool performUsernameCheck = false; + int i; + char *pServicename = NULL; + char *pAuthToken = NULL; + + // Determine if we are supposed to perform the username check + // based on the arguments specified. + for (i = 0; i < argc; i++) + { + if (*(argv[i]) == 'U') + { + // The arguments indicate that we should check the username + performUsernameCheck = true; + + // No need to keep going through the arguments + break; + } + } + + // Get the servicename. + if (pam_get_item(pamh, PAM_SERVICE, (void*) &pServicename) == PAM_SUCCESS + && pServicename != NULL) + { + // We got the service name, now check if it is necessary to perform + // the username check. + if (performUsernameCheck) + { + char *pUsername; + struct pam_response *responses = NULL; + + // Obtain the username so that it can be checked. + // . + // Note that we are not calling pam_get_user() because we + // assume that the service has set it before calling PAM_Authenticate. + if (pam_get_item(pamh, PAM_USER, (void*) &pUsername) == PAM_SUCCESS + && pUsername != NULL) + { + // Check if the username matches the name that we are expecting + if (strcmp(pUsername, "CasaPrincipal") != 0) + { + LogError("Un-expected username, %s", pUsername); + retStatus = PAM_USER_UNKNOWN; + } + } + else + { + struct pam_conv *pConv; + + // The username has not been set, try to obtain it from the + // application through the use of the conversation function. + if (pam_get_item(pamh, PAM_CONV, (void*) &pConv) == PAM_SUCCESS) + { + struct pam_message msg; + struct pam_message *messages = &msg; + + // Obtained the conversation structure, now query the conversation + // function for the username. + msg.msg_style = PAM_PROMPT_ECHO_ON; + if (pConv->conv(1, + (const struct pam_message **) &messages, + &responses, + pConv->appdata_ptr) == PAM_SUCCESS) + { + // Check if we have a successful response + if (responses[0].resp_retcode == PAM_SUCCESS + && responses[0].resp) + { + // Check if the username matches the name that we are expecting + if (strcmp(responses[0].resp, "CasaPrincipal") != 0) + { + LogError("Un-expected username, %s", responses[0].resp); + retStatus = PAM_USER_UNKNOWN; + } + } + else + { + LogError("Username not returned"); + retStatus = PAM_CRED_INSUFFICIENT; + } + } + else + { + LogError("Conversation function error"); + retStatus = PAM_AUTH_ERR; + } + } + else + { + LogError("Unable to obtain conversation structure"); + retStatus = PAM_AUTH_ERR; + } + } + + // Free conversation function response buffers if necessary + if (responses) + { + if (responses[0].resp) + free(responses[0].resp); + free(responses); + } + } + + // Proceed with the authentication token check if we have not encountered any + // problems. + if (retStatus == PAM_SUCCESS) + { + struct pam_response *responses = NULL; + + // Now obtain the authentication token. + if (pam_get_item(pamh, PAM_AUTHTOK, (void*) &pAuthToken) != PAM_SUCCESS + || pAuthToken == NULL) + { + struct pam_conv *pConv; + + // The authentication token has not been set, try to obtain it from the + // application through the use of the conversation function. + if (pam_get_item(pamh, PAM_CONV, (void*) &pConv) == PAM_SUCCESS) + { + struct pam_message msg; + struct pam_message *messages = &msg; + + // Obtained the conversation structure, now query the conversation + // function for the authentication token. + msg.msg_style = PAM_PROMPT_ECHO_OFF; + if (pConv->conv(1, + (const struct pam_message **) &messages, + &responses, + pConv->appdata_ptr) == PAM_SUCCESS) + { + // Check if we have a successful response + if (responses[0].resp_retcode == PAM_SUCCESS + && responses[0].resp) + { + // Set the authentication token with PAM + if (pam_set_item(pamh, PAM_AUTHTOK, responses[0].resp) == PAM_SUCCESS) + { + // Use the buffer returned by the caller as the authentication token + pAuthToken = responses[0].resp; + } + else + { + LogError("Unable to set the authentication token"); + } + } + else + { + LogError("Token not returned"); + } + } + else + { + LogError("Conversation function error"); + } + } + else + { + LogError("Unable to obtain conversation structure"); + } + } + + // Check if we succeeded at obtaining the authentication token + if (pAuthToken) + { + CasaStatus casaStatus; + PrincipalIf *pPrincipalIf; + + // Validate the token + casaStatus = ValidateAuthToken(pServicename, + pAuthToken, + strlen(pAuthToken), + &pPrincipalIf); + if (CASA_SUCCESS(casaStatus)) + { + int buffLen; + + // Assume success + retStatus = PAM_SUCCESS; + + // Associate necessary environment variables with the PAM Handle + buffLen = 0; + casaStatus = pPrincipalIf->getIdentityId(pPrincipalIf, + NULL, + &buffLen); + if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + char *pBuff; + + // Allocate buffer to contain the Identity Id Environment Variable + pBuff = malloc(sizeof(CasaIdentityIdEnvVar) + buffLen); + if (pBuff) + { + // Start constructing the environment variable + memcpy(pBuff, CasaIdentityIdEnvVar, sizeof(CasaIdentityIdEnvVar) - 1); + + // Read the value into our buffer + if (CASA_SUCCESS(pPrincipalIf->getIdentityId(pPrincipalIf, + pBuff + sizeof(CasaIdentityIdEnvVar) - 1, + &buffLen))) + { + // Now set the environment variable + if (pam_putenv(pamh, pBuff) != PAM_SUCCESS) + { + LogError("Unable to set identity id environment variable"); + retStatus = PAM_SYSTEM_ERR; + } + + // Also set the identity id as the username + if (pam_set_item(pamh, PAM_USER, pBuff + sizeof(CasaIdentityIdEnvVar) - 1) != PAM_SUCCESS) + { + LogError("Error setting the username"); + } + } + else + { + LogError("Unable to obtain identity id"); + retStatus = PAM_SYSTEM_ERR; + } + + // Free allocated buffer + free(pBuff); + } + else + { + LogError("Buffer allocation failure"); + retStatus = PAM_BUF_ERR; + } + } + else + { + LogError("Un-expected error obtaining identity id, %08X", casaStatus); + retStatus = PAM_SYSTEM_ERR; + } + + if (retStatus == PAM_SUCCESS) + { + buffLen = 0; + casaStatus = pPrincipalIf->getSourceName(pPrincipalIf, + NULL, + &buffLen); + if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + char *pBuff; + + // Allocate buffer to contain the Identity Source Name Environment Variable + pBuff = malloc(sizeof(CasaIdentitySourceNameEnvVar) + buffLen); + if (pBuff) + { + // Start constructing the environment variable + memcpy(pBuff, CasaIdentitySourceNameEnvVar, sizeof(CasaIdentitySourceNameEnvVar) - 1); + + // Read the value into our buffer + if (CASA_SUCCESS(pPrincipalIf->getSourceName(pPrincipalIf, + pBuff + sizeof(CasaIdentitySourceNameEnvVar) - 1, + &buffLen))) + { + // Now set the environment variable + if (pam_putenv(pamh, pBuff) != PAM_SUCCESS) + { + LogError("Unable to set identity source name environment variable"); + retStatus = PAM_SYSTEM_ERR; + } + } + else + { + LogError("Unable to obtain identity source name"); + retStatus = PAM_SYSTEM_ERR; + } + + // Free allocated buffer + free(pBuff); + } + else + { + LogError("Buffer allocation failure"); + retStatus = PAM_BUF_ERR; + } + } + else + { + LogError("Un-expected error obtaining identity source name, %08X", casaStatus); + retStatus = PAM_SYSTEM_ERR; + } + } + + if (retStatus == PAM_SUCCESS) + { + buffLen = 0; + casaStatus = pPrincipalIf->getSourceUrl(pPrincipalIf, + NULL, + &buffLen); + if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + char *pBuff; + + // Allocate buffer to contain the Identity Source Url Environment Variable + pBuff = malloc(sizeof(CasaIdentitySourceUrlEnvVar) + buffLen); + if (pBuff) + { + // Start constructing the environment variable + memcpy(pBuff, CasaIdentitySourceUrlEnvVar, sizeof(CasaIdentitySourceUrlEnvVar) - 1); + + // Read the value into our buffer + if (CASA_SUCCESS(pPrincipalIf->getSourceUrl(pPrincipalIf, + pBuff + sizeof(CasaIdentitySourceUrlEnvVar) - 1, + &buffLen))) + { + // Now set the environment variable + if (pam_putenv(pamh, pBuff) != PAM_SUCCESS) + { + LogError("Unable to set identity source url environment variable"); + retStatus = PAM_SYSTEM_ERR; + } + } + else + { + LogError("Unable to obtain identity source url"); + retStatus = PAM_SYSTEM_ERR; + } + + // Free allocated buffer + free(pBuff); + } + else + { + LogError("Buffer allocation failure"); + retStatus = PAM_BUF_ERR; + } + } + else + { + LogError("Un-expected error obtaining identity source url, %08X", casaStatus); + retStatus = PAM_SYSTEM_ERR; + } + } + + if (retStatus == PAM_SUCCESS) + { + char *pBuff; + int enumHandle = 0; + int buff2Len; + + while (retStatus == PAM_SUCCESS) + { + // Get attribute lengths + buffLen = buff2Len = 0; + casaStatus = pPrincipalIf->attributeEnumerate(pPrincipalIf, + &enumHandle, + NULL, + &buffLen, + NULL, + &buff2Len); + if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + // Allocate buffer to contain the Identity attribute Environment Variable + pBuff = malloc(buffLen + 2 + buff2Len); + if (pBuff) + { + // Read the attribute into our buffer + if (CASA_SUCCESS(pPrincipalIf->attributeEnumerate(pPrincipalIf, + &enumHandle, + pBuff, + &buffLen, + pBuff + buffLen + 1, // This includes the NULL terminator + &buff2Len))) + { + // Finish constructing the environment variable string + *(pBuff + buffLen - 1) = '='; + *(pBuff + buffLen) = ' '; + + // Now set the environment variable + if (pam_putenv(pamh, pBuff) != PAM_SUCCESS) + { + LogError("Unable to set identity attribute environment variable"); + retStatus = PAM_SYSTEM_ERR; + } + } + else + { + LogError("Unable to obtain identity attribute"); + retStatus = PAM_SYSTEM_ERR; + } + + // Free allocated buffer + free(pBuff); + } + else + { + LogError("Buffer allocation failure"); + retStatus = PAM_BUF_ERR; + } + } + else + { + // Check if we are done going through the attributes + if (CasaStatusCode(casaStatus) == CASA_STATUS_NO_MORE_ENTRIES) + { + // Done + break; + } + else + { + LogError("Un-expected error during attribute enumeration, %08X", casaStatus); + retStatus = PAM_SYSTEM_ERR; + } + } + } + } + + // Release the principal interface instance + pPrincipalIf->releaseReference(pPrincipalIf); + } + else + { + LogError("Service %s failed to authenticate with status = %08X", pServicename, casaStatus); + retStatus = PAM_AUTH_ERR; + } + } + else + { + LogError("Unable to obtain authentication token"); + retStatus = PAM_CRED_INSUFFICIENT; + } + + // Free conversation function response buffers if necessary + if (responses) + { + if (responses[0].resp) + free(responses[0].resp); + free(responses); + } + } + } + else + { + LogError("Unable to obtain servicename"); + retStatus = PAM_SYSTEM_ERR; + } + + return retStatus; +} + + +/* ************************************************************************ + * pam_sm_setcred() + * + * Service provider implementation for pam_setcred(). + * + * This is a PAM authentication management function. + * + * This function is here just for completedness and to protect against + * PAM misconfiguration. + * + * ************************************************************************/ +PAM_EXTERN int +pam_sm_setcred(pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + return PAM_SUCCESS; +} + + +/* ************************************************************************ + * pam_sm_acct_mgmt() + * + * Service provider implementation for pam_acct_mgmt(). + * + * This is a PAM account management function. + * + * This function is here just for completedness and to protect against + * PAM misconfiguration. + * + * ************************************************************************/ +PAM_EXTERN int +pam_sm_acct_mgmt(pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + return PAM_SUCCESS; +} + + +/* ************************************************************************ + * pam_sm_chauthtok() + * + * Service provider implementation for pam_chauthtok(). + * + * This is a PAM password management function. + * + * This function is here just for completedness and to protect against + * PAM misconfiguration. + * + * ************************************************************************/ +PAM_EXTERN int +pam_sm_chauthtok(pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + return PAM_SUCCESS; +} + + +/* ************************************************************************ + * pam_sm_open_session() + * + * Service provider implementation for pam_open_session(). + * + * This is a PAM session management function. + * + * This function is here just for completedness and to protect against + * PAM misconfiguration. + * + * ************************************************************************/ +PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + return PAM_SUCCESS; +} + + +/* ************************************************************************ + * pam_sm_close_session() + * + * Service provider implementation for pam_close_session(). + * + * This is a PAM session management function. + * + * This function is here just for completedness and to protect against + * PAM misconfiguration. + * + * ************************************************************************/ +PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, + int flags, + int argc, + const char **argv) +{ + return PAM_SUCCESS; +} + + +/* static module data */ +#ifdef PAM_STATIC +struct pam_module _pam_casa_authtoken_modstruct = { + "pam_casa_authtoken", + pam_sm_authenticate, + pam_sm_setcred, + pam_sm_acct_mgmt, + pam_sm_chauthtok, + pam_sm_open_session, + pam_sm_close_session +}; +#endif + diff --git a/CASA-auth-token/native/server/PamSupport/test/README b/CASA-auth-token/native/server/PamSupport/test/README new file mode 100644 index 00000000..5f975062 --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/test/README @@ -0,0 +1,32 @@ +/*********************************************************************** + * + * README for pamTest + * + ***********************************************************************/ + +INTRODUCTION + +pamTest is a PAM application which tests using CASA authentication tokens +for authentication. + +CONFIGURATION + +Place a copy of file testservice in the /etc/pam.d folder. + +BUILDING APPLICATION + +Execute script: make.sh. + +RUNNING APPLICATION + +Execute the following command: ./pamTest -s testService + + + + + + + + + + diff --git a/CASA-auth-token/native/server/PamSupport/test/make.sh b/CASA-auth-token/native/server/PamSupport/test/make.sh new file mode 100755 index 00000000..bb7d2da9 --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/test/make.sh @@ -0,0 +1,2 @@ +#!/bin/bash +gcc -o pamTest test.c -g -I"../../.." -I"../../../../include" -DN_PLAT_UNIX -L"../../../lib/Release" -lpam diff --git a/CASA-auth-token/native/server/PamSupport/test/test.c b/CASA-auth-token/native/server/PamSupport/test/test.c new file mode 100644 index 00000000..fb1b45b7 --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/test/test.c @@ -0,0 +1,520 @@ +/*********************************************************************** + * + * 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 +#include +#include +#include + +//===[ Type definitions ]================================================== + +typedef struct _AppUserData +{ + char *pUserName; + char *pAuthToken; + +} AppUserData, *PAppUserData; + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0) \ + printf(X, Y); \ + else if (DebugLevel >= LEVEL) \ + printf(X, Y); \ +} + +// +// Socket Mapping definitions +// +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define LINGER struct linger +#define SOCKADDR_IN struct sockaddr_in +#define closesocket close + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Usage string +char usage[] = "\nPamTest: usage: -s serviceName [-D DebugLevel]\n"; + +// Debug Level +int DebugLevel = 3; + +char *pServiceName = NULL; + +//++======================================================================= +int +Converse(int num_msg, + const struct pam_message **msg, + struct pam_response **resp, + void *appdata_ptr) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + int retStatus = PAM_SUCCESS; + int replies = 0; + struct pam_response *reply = NULL; + AppUserData *pAppUserData = (PAppUserData) appdata_ptr; + + // Initialize output parameters + *resp = NULL; + + // Check input parameters + if (num_msg <= 0 || appdata_ptr == NULL) + return PAM_CONV_ERR; + + // Allocate enough space for the replies + reply = malloc(sizeof(struct pam_response) * num_msg); + if (!reply) + return PAM_CONV_ERR; + + // Zero the reply buffer + memset(reply, 0, sizeof(struct pam_response) * num_msg); + + for (replies = 0; + replies < num_msg && retStatus == PAM_SUCCESS; + replies++) + { + switch (msg[replies]->msg_style) + { + case PAM_PROMPT_ECHO_ON: + + // The caller wants the username + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = malloc(strlen(pAppUserData->pUserName) + 1); + if (reply[replies].resp) + strcpy(reply[replies].resp, pAppUserData->pUserName); + else + { + DbgTrace(0, "Converse- Buffer allocation failure\n", 0); + retStatus = PAM_CONV_ERR; + } + break; + + case PAM_PROMPT_ECHO_OFF: + + // The caller wants the authentication token + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = malloc(strlen(pAppUserData->pAuthToken) + 1); + if (reply[replies].resp) + { + strcpy(reply[replies].resp, pAppUserData->pAuthToken); + } + else + { + DbgTrace(0, "Converse- Buffer allocation failure\n", 0); + retStatus = PAM_CONV_ERR; + } + break; + + case PAM_TEXT_INFO: + case PAM_ERROR_MSG: + + // Just return success + reply[replies].resp_retcode = PAM_SUCCESS; + reply[replies].resp = NULL; + break; + + default: + + // Un-expected + retStatus = PAM_CONV_ERR; + } + } + + // Proceed based on the status + if (retStatus == PAM_SUCCESS) + { + *resp = reply; + } + else + { + // Free buffers allocated for the reply + for (replies = 0; + replies < num_msg && retStatus == PAM_SUCCESS; + replies++) + { + if (reply[replies].resp != NULL) + free(reply[replies].resp); + } + free(reply); + } + + return retStatus; +} + + +//++======================================================================= +int +ReadLineIntoBuffer(int connSock, char *pBuffer) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + int i = 0; + char c; + int bytesReceived = 0; + + DbgTrace(2, "ReadLineIntoBuffer- Start\n", 0); + + // Receive the line + while ((bytesReceived = recv(connSock, &c, 1, 0)) == 1) + { + if (c == '\n') + break; + else + { + pBuffer[i] = c; + i ++; + } + } + + // Check for a socket error + if (bytesReceived == 0) + { + DbgTrace(0, "ReadLineIntoBuffer- Socket error\n", 0); + } + + DbgTrace(2, "ReadLineIntoBuffer- End, lineLength = %d\n", i); + + return i; +} + + +//++======================================================================= +void +ProcessConnection(int connSock) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + char userName[] = "CasaPrincipal"; + char token[4096] = {0}; + char helloString[100] = {0}; + AppUserData appUserData = {userName, token}; + struct pam_conv conv = {Converse, &appUserData}; + pam_handle_t *pamh; + int pam_status; + + DbgTrace(1, "ProcessConnection- Start\n", 0); + + // We have received a connection + printf("\n\nConnection received\n"); + + // Receive the token + if (ReadLineIntoBuffer(connSock, token) == 0) + { + DbgTrace(0, "ProcessConnection- Error receiving token\n", 0); + goto exit; + } + //printf("Token received = %s\n", token); + + // We obtained authentication token credentials to authenticate + // to the service, now verify the credentials using PAM_Authenticate. + // + // Open a PAM Handle + pam_status = pam_start(pServiceName, userName, &conv, &pamh); + if (pam_status == PAM_SUCCESS) + { + // Now authenticate the user + pam_status = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK); + if (pam_status == PAM_SUCCESS) + { + char **pam_envlist; + char **pam_env; + char *pUsername; + + DbgTrace(1, "ProcessConnection- pam_authenticate success\n", 0); + printf("Authentication succeeded\n"); + printf("The DUDE is cool\n"); + + // Get the identity information about the DUDE + + // Notice that the username may have been updated during the authentication process + if (pam_get_item(pamh, PAM_USER, (void*) &pUsername) == PAM_SUCCESS + && pUsername != NULL) + { + printf("The username of the authenticated identity is %s\n", pUsername); + } + else + { + DbgTrace(0, "ProcessConnection- pam_get_item did not return the username\n", 0); + } + + // Show identity information obtained during the authentication process and maintained + // as PAM environment variables. + pam_envlist = pam_getenvlist(pamh); + if (pam_envlist != NULL) + { + // Display the environment variables and free the memory associated + // with them. + for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) + { + printf("%s\n", *pam_env); + free(*pam_env); + } + free(pam_envlist); + } + else + { + DbgTrace(0, "ProcessConnection- pam_getenvlist did not return any data\n", 0); + } + } + else + { + DbgTrace(0, "ProcessConnection- pam_authenticate failure, error = %s\n", pam_strerror(pamh, pam_status)); + printf("The DUDE is a fake\n"); + } + + // Close the PAM Handle + pam_end(pamh, pam_status | PAM_DATA_SILENT); + } + else + { + DbgTrace(0, "ProcessConnection- pam_start failure, status = %08X\n", pam_status); + } + +exit: + + DbgTrace(1, "ProcessConnection- End\n", 0); +} + + +//++======================================================================= +void +ExecuteTests(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +//=======================================================================-- +{ + int connSock; + int listenSock; + struct sockaddr_in localAddr = {0}; + struct sockaddr_in boundAddr = {0}; + struct sockaddr_in remoteAddr = {0}; + struct linger linger_opt = {1, 15}; + int on = 1; + socklen_t addrLen = sizeof(struct sockaddr_in); + + DbgTrace(1, "ExecuteTests- Start\n", 0); + + // Open listen socket + listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (listenSock != INVALID_SOCKET) + { + // Setup the local address structure + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Set the SO_REUSEADDR option on the socket to avoid + // problems in case of a re-start. + setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + + // Bind socket + if (!bind(listenSock, (const struct sockaddr*) &localAddr, sizeof(struct sockaddr_in))) + { + // Display the local address information + if (getsockname(listenSock, + (struct sockaddr*) &boundAddr, + &addrLen) != SOCKET_ERROR) + { + printf("Listen port = %d\n", boundAddr.sin_port); + + // Now start linstening for connections + if (listen(listenSock, SOMAXCONN) != SOCKET_ERROR) + { + // Loop accepting connections + while (1) + { + addrLen = sizeof(remoteAddr); + connSock = accept(listenSock, + (struct sockaddr*) &remoteAddr, + &addrLen); + if (connSock != INVALID_SOCKET) + { + ProcessConnection(connSock); + + // Close the connection socket + closesocket(connSock); + } + else + { + DbgTrace(0, "ExecuteTests- - Accept failed, error = %08X\n", errno); + break; + } + } + } + else + { + DbgTrace(0, "ExecuteTests- Unable to start listening, error = %d", errno); + } + } + else + { + DbgTrace(0, "ExecuteTests- Unable to obtain local address information, error = %d", errno); + } + } + else + { + DbgTrace(0, "ExecuteTests- Unable to bind socket, error = %d", errno); + } + + // Close the listen socket + closesocket(listenSock); + } + else + { + DbgTrace(0, "ExecuteTests- Unable to open socket, error = %d\n", errno); + } + + DbgTrace(1, "ExecuteTests- End\n", 0); +} + + +//++======================================================================= +int +main( + int argc, + char* argv[]) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int optionsSpecified = 0; + bool doneScanning = false; + bool invalidOption = false; + int option; + + printf("**** server auth_token test ****\n"); + + // Scan through the options specified + while (!doneScanning) + { + opterr = 0; + option = getopt(argc, argv, "s:D:"); + + // Proceed based on the result + switch (option) + { + case 'D': + // Set the debug level + printf("DebugLevel = %s\n", optarg); + DebugLevel = atoi(optarg); + optionsSpecified++; + break; + + case 's': + // Set the service name + printf("Service name = %s\n", optarg); + pServiceName = optarg; + optionsSpecified++; + break; + + case '?': + // Invalid option detected + doneScanning = true; + invalidOption = true; + break; + + default: + // Done scanning + doneScanning = true; + break; + } + } + + // Do some sanity checking + if (!invalidOption + && pServiceName != NULL) + { + ExecuteTests(); + } + else + { + // Invalid option detected + printf(usage, argv[0]); + } + + return 0; + +} /*-- main() --*/ + diff --git a/CASA-auth-token/native/server/PamSupport/test/testservice b/CASA-auth-token/native/server/PamSupport/test/testservice new file mode 100644 index 00000000..452e1efb --- /dev/null +++ b/CASA-auth-token/native/server/PamSupport/test/testservice @@ -0,0 +1,6 @@ +#%PAM-1.0 +auth required pam_casaauthtok.so U +account required pam_casaauthtok.so +password required pam_casaauthtok.so +session required pam_casaauthtok.so +