signond-nicolasfella/0000775000175000017500000000000014615454547015062 5ustar coucoufcoucoufsignond-nicolasfella/.qmake.conf0000664000175000017500000000006614615454535017104 0ustar coucoufcoucoufTOP_SRC_DIR = $$PWD TOP_BUILD_DIR = $$shadowed($$PWD) signond-nicolasfella/COPYING0000664000175000017500000006350214615454535016120 0ustar coucoufcoucouf GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, 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 How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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; either version 2.1 of the License, or (at your option) any later version. 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 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! signond-nicolasfella/INSTALL0000664000175000017500000000125614615454535016114 0ustar coucoufcoucoufBuilding signond can be done by typing these commands: qmake [options] make make install Note that the "make install" command will probably require root permission in order to install the files into the root filesystem. The options recognized by the qmake command are: PREFIX= (default is "/usr") LIBDIR= (default is "$PREFIX/lib" on 32bit machines and "$PREFIX/lib64" on 64bit machines) CONFIG+=coverage (enable test coverage reporting) CONFIG+=cryptsetup (enable building the cryptsetup extension) Example: qmake PREFIX=~ CONFIG+=cryptsetup signond-nicolasfella/NOTES0000664000175000017500000000000114615454535015661 0ustar coucoufcoucouf signond-nicolasfella/README.md0000664000175000017500000000113014615454535016331 0ustar coucoufcoucoufSignOn daemon ============= The SignOn daemon is a D-Bus service which performs user authentication on behalf of its clients. There are currently authentication plugins for OAuth 1.0 and 2.0, SASL, Digest-MD5, and plain username/password combination. License ------- See COPYING file. Build instructions ------------------ This project depends on Qt 5. To build it, run ``` qmake make make install ``` Resources --------- [libsignon-qt API reference documentation](http://accounts-sso.gitlab.io/signond/index.html) [Official source code repository](https://gitlab.com/accounts-sso/signond) signond-nicolasfella/TODO0000664000175000017500000000000114615454535015536 0ustar coucoufcoucouf signond-nicolasfella/common-installs-config.pri0000664000175000017500000000263514615454535022163 0ustar coucoufcoucouf#----------------------------------------------------------------------------- # Common installation configuration for all projects. #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # default installation target for applications #----------------------------------------------------------------------------- contains( TEMPLATE, app ) { target.path = $${INSTALL_PREFIX}/bin INSTALLS += target message("====") message("==== INSTALLS += target") } #----------------------------------------------------------------------------- # default installation target for libraries #----------------------------------------------------------------------------- contains( TEMPLATE, lib ) { target.path = $${INSTALL_LIBDIR} INSTALLS += target message("====") message("==== INSTALLS += target") } #----------------------------------------------------------------------------- # target for header files #----------------------------------------------------------------------------- !isEmpty( headers.files ) { headers.path = $${INSTALL_PREFIX}/include/$${TARGET} INSTALLS += headers message("====") message("==== INSTALLS += headers") } else { message("====") message("==== NOTE: Remember to add your API headers into `headers.files' for installation!") } # End of File signond-nicolasfella/common-pkgconfig.pri0000664000175000017500000000046514615454535021035 0ustar coucoufcoucouf# Include this file after defining the pkgconfig.files variable !isEmpty(pkgconfig.files) { QMAKE_SUBSTITUTES += $${pkgconfig.files}.in pkgconfig.CONFIG = no_check_exist pkgconfig.path = $${INSTALL_LIBDIR}/pkgconfig QMAKE_EXTRA_TARGETS += pkgconfig QMAKE_CLEAN += $${pkgconfig.files} } signond-nicolasfella/common-vars.pri0000664000175000017500000000171214615454535020035 0ustar coucoufcoucouf#----------------------------------------------------------------------------- # Common variables for all projects. #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Project name (used e.g. in include file and doc install path). # remember to update debian/* files if you changes this #----------------------------------------------------------------------------- PROJECT_NAME = signon #----------------------------------------------------------------------------- # Project version # remember to update debian/* files if you changes this #----------------------------------------------------------------------------- PROJECT_VERSION = 8.61 #----------------------------------------------------------------------------- # Library version #----------------------------------------------------------------------------- LIBRARY_VERSION = 0.4 # End of File signond-nicolasfella/coverage.pri0000664000175000017500000000367114615454535017375 0ustar coucoufcoucouf# Coverage CONFIG(coverage) { OBJECTS_DIR = MOC_DIR = TOP_SRC_DIR = $$PWD LIBS += -lgcov QMAKE_CXXFLAGS += --coverage QMAKE_LDFLAGS += --coverage QMAKE_EXTRA_TARGETS += coverage cov QMAKE_EXTRA_TARGETS += clean-gcno clean-gcda coverage-html \ generate-coverage-html clean-coverage-html coverage-gcovr \ generate-gcovr generate-coverage-gcovr clean-coverage-gcovr clean-gcno.commands = \ "@echo Removing old coverage instrumentation"; \ "find -name '*.gcno' -print | xargs -r rm" clean-gcda.commands = \ "@echo Removing old coverage results"; \ "find -name '*.gcda' -print | xargs -r rm" coverage-html.depends = clean-gcda check generate-coverage-html generate-coverage-html.commands = \ "@echo Collecting coverage data"; \ "lcov --directory $${TOP_SRC_DIR} --capture --output-file coverage.info --no-checksum --compat-libtool"; \ "lcov --extract coverage.info \"*/src/*.cpp\" --extract coverage.info \"*/lib/*.cpp\" -o coverage.info"; \ "lcov --remove coverage.info \"moc_*.cpp\" --remove coverage.info \"*/test/*\" -o coverage.info"; \ "LANG=C genhtml --prefix $${TOP_SRC_DIR} --output-directory coverage-html --title \"Code Coverage\" --legend --show-details coverage.info" clean-coverage-html.depends = clean-gcda clean-coverage-html.commands = \ "lcov --directory $${TOP_SRC_DIR} -z"; \ "rm -rf coverage.info coverage-html" coverage-gcovr.depends = clean-gcda check generate-coverage-gcovr generate-coverage-gcovr.commands = \ "@echo Generating coverage GCOVR report"; \ "gcovr -x -r $${TOP_SRC_DIR} -o $${TOP_SRC_DIR}/coverage.xml -e \".*/moc_.*\" -e \"tests/.*\" -e \".*\\.h\"" clean-coverage-gcovr.depends = clean-gcda clean-coverage-gcovr.commands = \ "rm -rf $${TOP_SRC_DIR}/coverage.xml" QMAKE_CLEAN += *.gcda *.gcno coverage.info coverage.xml } signond-nicolasfella/doc/0000775000175000017500000000000014615454535015624 5ustar coucoufcoucoufsignond-nicolasfella/doc/doc.pri0000664000175000017500000000525314615454535017112 0ustar coucoufcoucouf#----------------------------------------------------------------------------- # doc.pri #----------------------------------------------------------------------------- # list of documentation folders to install DOC_FOLDERS = doc/html \ doc/qch # files and folders listed in the installation target's .files section # must exist _before_ qmake generates the Makefile...so, make sure our # documentation target folders exist in the current build folder for( folder, DOC_FOLDERS ) { system( mkdir -p $$OUT_PWD/$${folder} ) } #----------------------------------------------------------------------------- # extra build targets for generating and cleaning documentation #----------------------------------------------------------------------------- DOC_INPUT += $${_PRO_FILE_PWD_}/doc/src # target for generating documentation doctarget.target = docs doctarget.commands = OUTPUT_DIRECTORY=doc \ PROJECT_NAME=\"$${PROJECT_NAME}\" \ PROJECT_NUMBER=\"$${PROJECT_VERSION}\" \ STRIP_FROM_PATH=\"$${_PRO_FILE_PWD_}\" \ INPUT=\"$${DOC_INPUT}\" \ QHP_NAMESPACE=\"com.nokia.example.$${TARGET}\" \ QHP_VIRTUAL_FOLDER=\"$${TARGET}\" \ TAGFILES=\"$$system(pwd)/qt.tags\" \ TAGFILE=\"doc/$${TARGET}.tags\" \ doxygen $$system(pwd)/doxy.conf doctarget.depends = FORCE QMAKE_EXTRA_TARGETS += doctarget # target for cleaning generated documentation doccleantarget.target = cleandocs for( folder, DOC_FOLDERS ) { doccleantarget.commands += rm -r -f $${folder}; } doccleantarget.commands += rm -r -f doc/signon.tags; doccleantarget.depends = FORCE QMAKE_EXTRA_TARGETS += doccleantarget #----------------------------------------------------------------------------- # installation setup # NOTE: remember to set headers.files before this include to have the headers # properly setup. #----------------------------------------------------------------------------- include( ../common-project-config.pri ) include( ../common-installs-config.pri ) #----------------------------------------------------------------------------- # Installation target setup for documentation #----------------------------------------------------------------------------- documentation.path = $${INSTALL_PREFIX}/share/doc/$${PROJECT_NAME} for( folder, DOC_FOLDERS ) { documentation.files += $$OUT_PWD/$${folder} } # make sure docs are generated before trying to install anything documentation.depends = docs INSTALLS += documentation message("====") message("==== INSTALLS += documentation") # End of File signond-nicolasfella/doc/doxy.conf0000664000175000017500000017331514615454535017470 0ustar coucoufcoucouf# Doxyfile 1.5.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = $(PROJECT_NAME) # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = $(PROJECT_NUMBER) # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = $(OUTPUT_DIRECTORY) # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, # Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = $(STRIP_FROM_PATH) # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = $(INPUT) # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.cpp \ *.h \ *.dox # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = debian \ builddir # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */.moc/* \ */.obj/* \ */.git/* \ */tests/* \ */moc_* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = YES # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = ../qch/signon.qch # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = $(QHP_NAMESPACE) # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = $(QHP_VIRTUAL_FOLDER) # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = qhelpgenerator # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to FRAME, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = ALL # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = $(TAGFILES) # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = $(TAGFILE) # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO # End of File signond-nicolasfella/doc/src/0000775000175000017500000000000014615454535016413 5ustar coucoufcoucoufsignond-nicolasfella/doc/src/mainpage.dox0000664000175000017500000000070114615454535020706 0ustar coucoufcoucouf/*! @mainpage Single Sign On documentation @section intro Introduction Single Sign-On is a framework for centrally storing authentication credentials and handling authentication on behalf of applications as requested by applications. It consists of a secure storage of login credentials (for example usernames and passwords), plugins for different authentication systems and a client library for applications to communicate with this system. */ signond-nicolasfella/lib/0000775000175000017500000000000014615454535015625 5ustar coucoufcoucoufsignond-nicolasfella/lib/SignOn/0000775000175000017500000000000014615454547017025 5ustar coucoufcoucoufsignond-nicolasfella/lib/SignOn/AuthService0000664000175000017500000000004114615454535021162 0ustar coucoufcoucouf#include signond-nicolasfella/lib/SignOn/AuthSession0000664000175000017500000000004114615454535021205 0ustar coucoufcoucouf#include signond-nicolasfella/lib/SignOn/Error0000664000175000017500000000004014615454535020030 0ustar coucoufcoucouf#include signond-nicolasfella/lib/SignOn/Identity0000664000175000017500000000003614615454535020535 0ustar coucoufcoucouf#include signond-nicolasfella/lib/SignOn/IdentityInfo0000664000175000017500000000004214615454535021346 0ustar coucoufcoucouf#include signond-nicolasfella/lib/SignOn/SecurityContext0000664000175000017500000000004514615454535022120 0ustar coucoufcoucouf#include signond-nicolasfella/lib/SignOn/SessionData0000664000175000017500000000004114615454535021155 0ustar coucoufcoucouf#include signond-nicolasfella/lib/SignOn/SignOn.pro0000664000175000017500000000020314615454535020734 0ustar coucoufcoucoufTEMPLATE = subdirs CONFIG += ordered SUBDIRS = \ libsignon-qt-shared.pro \ libsignon-qt-static.pro include(doc/doc.pri) signond-nicolasfella/lib/SignOn/SignOnQt5ConfigVersion.cmake.in0000664000175000017500000000100014615454535024703 0ustar coucoufcoucoufset(PACKAGE_VERSION $${PROJECT_VERSION}) if(\"${PACKAGE_VERSION}\" VERSION_LESS \"${PACKAGE_FIND_VERSION}\" ) set(PACKAGE_VERSION_COMPATIBLE FALSE) else(\"${PACKAGE_VERSION}\" VERSION_LESS \"${PACKAGE_FIND_VERSION}\" ) set(PACKAGE_VERSION_COMPATIBLE TRUE) if( \"${PACKAGE_FIND_VERSION}\" STREQUAL \"${PACKAGE_VERSION}\") set(PACKAGE_VERSION_EXACT TRUE) endif( \"${PACKAGE_FIND_VERSION}\" STREQUAL \"${PACKAGE_VERSION}\") endif(\"${PACKAGE_VERSION}\" VERSION_LESS \"${PACKAGE_FIND_VERSION}\" ) signond-nicolasfella/lib/SignOn/async-dbus-proxy.cpp0000664000175000017500000002346114615454535022763 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "async-dbus-proxy.h" #include #include #include #include #include #include #include "connection-manager.h" #include "dbusinterface.h" #include "debug.h" #include "libsignoncommon.h" #include "signond/signoncommon.h" using namespace SignOn; namespace SignOn { class Connection { public: Connection(const char *name, QObject *receiver, const char *slot): m_name(name), m_receiver(receiver), m_slot(slot) { } ~Connection() {} const char *m_name; QObject *m_receiver; const char *m_slot; }; } // namespace PendingCall::PendingCall(const QString &method, const QList &args, QObject *parent): QObject(parent), m_method(method), m_args(args), m_watcher(0), m_interfaceWasDestroyed(false) { } PendingCall::~PendingCall() { } bool PendingCall::cancel() { if (m_watcher) { // Too late, can't cancel return false; } Q_EMIT finished(0); return true; } void PendingCall::doCall(QDBusAbstractInterface *interface) { QDBusPendingCall call = interface->asyncCallWithArgumentList(m_method, m_args); m_watcher = new QDBusPendingCallWatcher(call, this); QObject::connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(onFinished(QDBusPendingCallWatcher*))); /* Check if the interface gets destroyed while our call executes */ m_interfaceWasDestroyed = false; QObject::connect(interface, SIGNAL(destroyed()), this, SLOT(onInterfaceDestroyed())); } void PendingCall::fail(const QDBusError &err) { Q_EMIT error(err); Q_EMIT finished(0); } void PendingCall::onFinished(QDBusPendingCallWatcher *watcher) { /* Check if the call failed because the interface became invalid; if * so, emit a signal to instruct the AsyncDBusProxy to re-queue this * operation. */ if (m_interfaceWasDestroyed && watcher->isError()) { QDBusError::ErrorType type = watcher->error().type(); if (type == QDBusError::Disconnected || type == QDBusError::UnknownObject) { TRACE() << "emitting retry signal"; Q_EMIT requeueRequested(); return; } } if (watcher->isError()) { Q_EMIT error(watcher->error()); } else { Q_EMIT success(watcher); } Q_EMIT finished(watcher); } void PendingCall::onInterfaceDestroyed() { /* If the interface is destroyed during the lifetime of the call, this can * be because the remote object got destroyed or the D-Bus connection * dropped. In either case, we might have to re-queue our method call. * * This is done in the onFinished() slot; here we just record the event. */ m_interfaceWasDestroyed = true; } AsyncDBusProxy::AsyncDBusProxy(const QString &service, const char *interface, QObject *clientObject): m_serviceName(service), m_interfaceName(interface), m_connection(NULL), m_clientObject(clientObject), m_interface(NULL), m_status(Incomplete) { } AsyncDBusProxy::~AsyncDBusProxy() { qDeleteAll(m_connectionsQueue); m_connectionsQueue.clear(); delete m_connection; } void AsyncDBusProxy::setStatus(Status status) { m_status = status; if (status == Ready) { /* connect the signals and execute all pending methods */ Q_FOREACH(Connection *connection, m_connectionsQueue) { m_interface->connect(connection->m_name, connection->m_receiver, connection->m_slot); } Q_FOREACH(PendingCall *call, m_operationsQueue) { call->doCall(m_interface); } m_operationsQueue.clear(); } else if (status == Invalid) { /* signal error on all operations */ Q_FOREACH(PendingCall *call, m_operationsQueue) { call->fail(m_lastError); } m_operationsQueue.clear(); } } void AsyncDBusProxy::update() { if (m_interface != NULL) { delete m_interface; m_interface = 0; } if (m_connection == NULL || m_path.isEmpty()) { setStatus(Incomplete); return; } if (!m_connection->isConnected()) { setError(m_connection->lastError()); return; } m_interface = new DBusInterface(m_serviceName, m_path, m_interfaceName, *m_connection, this); setStatus(Ready); } void AsyncDBusProxy::setConnection(const QDBusConnection &connection) { delete m_connection; m_connection = new QDBusConnection(connection); update(); } void AsyncDBusProxy::setDisconnected() { TRACE(); delete m_connection; m_connection = 0; /* The daemon is dead, so certainly the object paths are also invalid */ m_path = QString(); update(); } void AsyncDBusProxy::setObjectPath(const QDBusObjectPath &objectPath) { Q_ASSERT(m_path.isEmpty() || objectPath.path().isEmpty()); m_path = objectPath.path(); update(); } void AsyncDBusProxy::setError(const QDBusError &error) { TRACE() << error; m_lastError = error; setStatus(Invalid); } PendingCall *AsyncDBusProxy::queueCall(const QString &method, const QList &args, const char *replySlot, const char *errorSlot) { return queueCall(method, args, m_clientObject, replySlot, errorSlot); } PendingCall *AsyncDBusProxy::queueCall(const QString &method, const QList &args, QObject *receiver, const char *replySlot, const char *errorSlot) { PendingCall *call = new PendingCall(method, args, this); QObject::connect(call, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(onCallFinished(QDBusPendingCallWatcher*))); QObject::connect(call, SIGNAL(requeueRequested()), this, SLOT(onRequeueRequested())); if (errorSlot) { QObject::connect(call, SIGNAL(error(const QDBusError&)), receiver, errorSlot); if (replySlot) { QObject::connect(call, SIGNAL(success(QDBusPendingCallWatcher*)), receiver, replySlot); } } else if (replySlot) { QObject::connect(call, SIGNAL(finished(QDBusPendingCallWatcher*)), receiver, replySlot); } if (m_status == Ready) { call->doCall(m_interface); } else if (m_status == Incomplete) { enqueue(call); } else { QMetaObject::invokeMethod(call, "fail", Qt::QueuedConnection, Q_ARG(QDBusError, m_lastError)); } return call; } bool AsyncDBusProxy::connect(const char *name, QObject *receiver, const char *slot) { /* Remember all the connections anyway, because we'll re-play them if we * disconnect and reconnect again */ Connection *connection = new Connection(name, receiver, slot); m_connectionsQueue.enqueue(connection); if (m_status == Ready) { return m_interface->connect(name, receiver, slot); } return true; } void AsyncDBusProxy::enqueue(PendingCall *call) { m_operationsQueue.enqueue(call); if (!m_connection) { Q_EMIT connectionNeeded(); } if (m_path.isEmpty()) { Q_EMIT objectPathNeeded(); } } void AsyncDBusProxy::onCallFinished(QDBusPendingCallWatcher *watcher) { Q_UNUSED(watcher); PendingCall *call = qobject_cast(sender()); m_operationsQueue.removeOne(call); call->deleteLater(); } void AsyncDBusProxy::onRequeueRequested() { PendingCall *call = qobject_cast(sender()); enqueue(call); } SignondAsyncDBusProxy::SignondAsyncDBusProxy(const char *interface, QObject *clientObject): AsyncDBusProxy(SIGNOND_SERVICE, interface, clientObject) { setupConnection(); } SignondAsyncDBusProxy::~SignondAsyncDBusProxy() { } void SignondAsyncDBusProxy::setupConnection() { ConnectionManager *connManager = ConnectionManager::instance(); QObject::connect(connManager, SIGNAL(connected(const QDBusConnection&)), this, SLOT(setConnection(const QDBusConnection&))); QObject::connect(connManager, SIGNAL(disconnected()), this, SLOT(setDisconnected())); QObject::connect(this, SIGNAL(connectionNeeded()), connManager, SLOT(connect())); if (connManager->hasConnection()) { setConnection(connManager->connection()); } } signond-nicolasfella/lib/SignOn/async-dbus-proxy.h0000664000175000017500000000761414615454535022432 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_ASYNC_DBUS_PROXY_H #define SIGNON_ASYNC_DBUS_PROXY_H #include #include #include #include class QDBusAbstractInterface; class QDBusConnection; class QDBusObjectPath; class QDBusPendingCallWatcher; /* * @cond IMPL */ namespace SignOn { class AsyncDBusProxy; class Connection; class DBusInterface; class PendingCall: public QObject { Q_OBJECT public: ~PendingCall(); bool cancel(); Q_SIGNALS: void finished(QDBusPendingCallWatcher *watcher); void success(QDBusPendingCallWatcher *watcher); void error(const QDBusError &error); void requeueRequested(); private Q_SLOTS: void onFinished(QDBusPendingCallWatcher *watcher); void onInterfaceDestroyed(); void fail(const QDBusError &error); private: friend class AsyncDBusProxy; PendingCall(const QString &method, const QList &args, QObject *parent = 0); void doCall(QDBusAbstractInterface *interface); private: QString m_method; QList m_args; QDBusPendingCallWatcher *m_watcher; bool m_interfaceWasDestroyed; }; class AsyncDBusProxy: public QObject { Q_OBJECT public: AsyncDBusProxy(const QString &service, const char *interface, QObject *clientObject); ~AsyncDBusProxy(); void setObjectPath(const QDBusObjectPath &objectPath); void setError(const QDBusError &error); PendingCall *queueCall(const QString &method, const QList &args, const char *replySlot = 0, const char *errorSlot = 0); PendingCall *queueCall(const QString &method, const QList &args, QObject *receiver, const char *replySlot, const char *errorSlot); bool connect(const char *name, QObject *receiver, const char *slot); public Q_SLOTS: void setConnection(const QDBusConnection &connection); void setDisconnected(); Q_SIGNALS: void connectionNeeded(); void objectPathNeeded(); private: enum Status { Incomplete, Ready, Invalid }; void setStatus(Status status); void update(); void enqueue(PendingCall *call); private Q_SLOTS: void onCallFinished(QDBusPendingCallWatcher *watcher); void onRequeueRequested(); private: QString m_serviceName; const char *m_interfaceName; QString m_path; QDBusConnection *m_connection; QObject *m_clientObject; QQueue m_operationsQueue; QQueue m_connectionsQueue; DBusInterface *m_interface; Status m_status; QDBusError m_lastError; }; class SignondAsyncDBusProxy: public AsyncDBusProxy { Q_OBJECT public: SignondAsyncDBusProxy(const char *interface, QObject *clientObject); ~SignondAsyncDBusProxy(); private: void setupConnection(); }; } //SignOn /* * @endcond IMPL */ #endif // SIGNON_ASYNC_DBUS_PROXY_H signond-nicolasfella/lib/SignOn/authservice.cpp0000664000175000017500000000323414615454535022052 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "authservice.h" #include "authserviceimpl.h" #include "debug.h" namespace SignOn { AuthService::AuthService(QObject *parent): QObject(parent), impl(new AuthServiceImpl(this)) { initDebug(); qRegisterMetaType("SignOn::Error"); qRegisterMetaType("Error"); if (qMetaTypeId() < QMetaType::User) BLAME() << "AuthService::AuthService() - " "SignOn::Error meta type not registered."; } AuthService::~AuthService() { } void AuthService::queryMethods() { impl->queryMethods(); } void AuthService::queryMechanisms(const QString &method) { impl->queryMechanisms(method); } void AuthService::queryIdentities(const IdentityFilter &filter) { impl->queryIdentities(filter); } void AuthService::clear() { impl->clear(); } } //namespace SignOn signond-nicolasfella/lib/SignOn/authservice.h0000664000175000017500000001743314615454535021525 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef AUTHSERVICE_H #define AUTHSERVICE_H #include #include #include #include "libsignoncommon.h" #include "identityinfo.h" #include "signonerror.h" namespace SignOn { /*! * @class AuthService * @headerfile authservice.h SignOn/AuthService * * Represents signon for client application. * The class is for managing identities. * Most applications can use this by using widgets from libSignOnUI. */ class SIGNON_EXPORT AuthService: public QObject { Q_OBJECT Q_DISABLE_COPY(AuthService) friend class AuthServiceImpl; public: /*! * @enum ServiceError * Codes for errors that may be reported by AuthService objects. * @deprecated This enum is deprecated. Replaced by Error::ErrorType. */ enum ServiceError { UnknownError = 1, /**< Catch-all for errors not distinguished by another code. */ InternalServerError = 2, /**< Signon Daemon internal error. */ InternalCommunicationError = 3, /**< Communication with Signon Daemon error. */ PermissionDeniedError = 4, /**< The operation cannot be performed due to insufficient client permissions. */ AuthServiceErr = 100, /* Placeholder to rearrange enumeration */ MethodNotKnownError, /**< The method with this name is not found. */ NotAvailableError, /**< The service is temporarily unavailable. */ InvalidQueryError /**< Parameters for the query are invalid. */ }; /*! * @enum IdentityFilterCriteria * Criterias for idetity query filtering. * @see AuthService::queryIdentities() */ typedef enum { AuthMethod = 0, Username, Realm, Caption } IdentityFilterCriteria; /*! * @class IdentityRegExp * The class represents a regular expression. * It is used for filtering identity querying. * @see queryIdentities() * @note This is for internal use only. */ class IdentityRegExp { public: /*! * Constructor creates an IdentityRegExp, as a specified by pattern. * @param pattern The regular expression as a string */ IdentityRegExp(const QString &pattern); /*! * Copy constructor, creates a copy of src. * @param src The IdentityRegExp to be copied */ IdentityRegExp(const IdentityRegExp &src); /*! * Returns the validity of regular expression. * @return Always false, validity check not implemented. */ bool isValid() const; /*! * Returns the pattern of regular expression as string. * @return The pattern of this regular expression as string. */ QString pattern() const; private: QString m_pattern; }; public: /*! * @typedef IdentityFilter * Map to hold different filtering options. */ typedef QMap IdentityFilter; /*! * Basic constructor * @param parent Parent object */ AuthService(QObject *parent = 0); /*! * Destructor */ ~AuthService(); /*! * Requests the information on available authentication methods. * The list of service types retrieved * is emitted with signal methodsAvailable(). * Error is reported by emitting signal error(). * * @see AuthService::methodsAvailable() * @see AuthService::error() */ void queryMethods(); /*! * Requests the information on mechanisms which are available * for certain authentication type. * The list of mechanisms retrieved from the service * is emitted with signal mechanismsAvailable(). * Error is reported by emitting signal error(). * If method is not a valid method, Error::type() is * Error::MethodNotKnown. * * @see AuthService::mechanismsAvailable() * @see AuthService::error() * @param method authetication method name */ void queryMechanisms(const QString &method); /*! * Requests information on identities which are stored. * The list of identities retrieved from the service * is emitted with signal identities(). * Error is reported by emitting signal error(). * If filter is not valid, Error::type() is * Error::InvalidQuery. * If the application does not have keychain-access credential, * Error::type() is Error::PermissionDenied. * * @see AuthService::identities() * @see AuthService::error() * @param filter Shows only identities specified in filter - filtering not implemented for the moment. * If default parameter is passed, all the identities are returned. * @credential keychain-access key-chain application can access list of identities. */ void queryIdentities(const IdentityFilter &filter = IdentityFilter()); /*! * Clears credentials database. All identity entries are removed from database. * Signal cleared() is emitted when operation is completed. * Error is reported by emitting signal error(). * If the application does not have keychain-access credential, * Error::type() is Error::PermissionDenied. * * @see AuthService::cleared() * @see AuthService::error() * @credential keychain-access key-chain application can clear database. */ void clear(); Q_SIGNALS: /*! * Emitted when an error occurs while using the AuthService. * Typical error types are generic errors, where * Error::type() < Error::AuthServiceErr and * AuthService specific, where * Error::AuthServiceErr < Error::type() < Error::IdentityErr * @see SignOn::Error * @see SignOn::Error::ErrorType * @param err The error object */ void error(const SignOn::Error &err); /*! * Emitted when the list of available authentication methods have been obtained * from the service. * * @param methods List of available authentication method names */ void methodsAvailable(const QStringList &methods); /*! * Emitted when the list of available mechanisms have been obtained * from the service. * * @param method Name of authentication method that was queried * @param mechanisms List of available mechanisms */ void mechanismsAvailable(const QString &method, const QStringList &mechanisms); /*! * Lists identities available on the server matching query parameters. * This signal is emitted in response to queryIdentities(). * * @param identityList list of identities information */ void identities(const QList &identityList); /*! * Database is cleared and reset to initial state. * This signal is emitted in response to clear(). */ void cleared(); private: class AuthServiceImpl *impl; }; } // namespace SignOn #endif // AUTHSERVICE_H signond-nicolasfella/lib/SignOn/authserviceimpl.cpp0000664000175000017500000001567014615454535022743 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include "signond/signoncommon.h" #include "debug.h" #include "libsignoncommon.h" #include "identityinfo.h" #include "identityinfoimpl.h" #include "authserviceimpl.h" #include "signonerror.h" using namespace SignOn; /* ----------------------- IdentityRegExp ----------------------- */ AuthService::IdentityRegExp::IdentityRegExp(const QString &pattern): m_pattern(pattern) { } AuthService::IdentityRegExp::IdentityRegExp(const IdentityRegExp &src): m_pattern(src.pattern()) { } bool AuthService::IdentityRegExp::isValid() const { return false; } QString AuthService::IdentityRegExp::pattern() const { return m_pattern; } /* ----------------------- AuthServiceImpl ----------------------- */ AuthServiceImpl::AuthServiceImpl(AuthService *parent): QObject(parent), m_parent(parent), m_dbusProxy(SIGNOND_DAEMON_INTERFACE_C, this) { TRACE(); m_dbusProxy.setObjectPath(QDBusObjectPath(SIGNOND_DAEMON_OBJECTPATH)); qDBusRegisterMetaType(); } AuthServiceImpl::~AuthServiceImpl() { } void AuthServiceImpl::queryMethods() { sendRequest(QLatin1String("queryMethods"), SLOT(queryMethodsReply(QDBusPendingCallWatcher*)), QVariantList()); } void AuthServiceImpl::queryMechanisms(const QString &method) { m_dbusProxy.queueCall(QLatin1String("queryMechanisms"), QVariantList() << method, SLOT(queryMechanismsReply(QDBusPendingCallWatcher*)), SLOT(queryMechanismsError(const QDBusError&))); m_methodsForWhichMechsWereQueried.enqueue(method); } void AuthServiceImpl::queryIdentities(const AuthService::IdentityFilter &filter) { if (!filter.isEmpty()) TRACE() << "Querying identities with filter not implemented."; QVariantList args; QMap filterMap; if (!filter.empty()) { QMapIterator it(filter); while (it.hasNext()) { it.next(); if (!it.value().isValid()) continue; const char *criteriaStr = 0; switch ((AuthService::IdentityFilterCriteria)it.key()) { case AuthService::AuthMethod: criteriaStr = "AuthMethod"; break; case AuthService::Username: criteriaStr = "Username"; break; case AuthService::Realm: criteriaStr = "Realm"; break; case AuthService::Caption: criteriaStr = "Caption"; break; default: break; } filterMap.insert(QLatin1String(criteriaStr), QVariant(it.value().pattern())); } } args << filterMap; /* TODO: implement the application security context */ args << QLatin1String("*"); sendRequest(QLatin1String("queryIdentities"), SLOT(queryIdentitiesReply(QDBusPendingCallWatcher*)), args); } void AuthServiceImpl::clear() { sendRequest(QLatin1String("clear"), SLOT(clearReply()), QList()); } void AuthServiceImpl::sendRequest(const QString &operation, const char *replySlot, const QList &args) { m_dbusProxy.queueCall(operation, args, replySlot, SLOT(errorReply(const QDBusError&))); } void AuthServiceImpl::queryMethodsReply(QDBusPendingCallWatcher *call) { QDBusPendingReply reply = *call; QStringList methods = reply.argumentAt<0>(); emit m_parent->methodsAvailable(methods); } void AuthServiceImpl::queryMechanismsReply(QDBusPendingCallWatcher *call) { QDBusPendingReply reply = *call; QStringList mechs = reply.argumentAt<0>(); TRACE() << mechs; QString method; if (!m_methodsForWhichMechsWereQueried.empty()) method = m_methodsForWhichMechsWereQueried.dequeue(); emit m_parent->mechanismsAvailable(method, mechs); } void AuthServiceImpl::queryMechanismsError(const QDBusError &err) { if (!m_methodsForWhichMechsWereQueried.empty()) { m_methodsForWhichMechsWereQueried.dequeue(); } errorReply(err); } void AuthServiceImpl::queryIdentitiesReply(QDBusPendingCallWatcher *call) { QDBusMessage msg = call->reply(); QList args = msg.arguments(); if (args.isEmpty()) { BLAME() << "Invalid reply: no arguments"; return; } QDBusArgument arg = args[0].value(); MapList identitiesData = qdbus_cast(arg); QList infoList; foreach (const QVariantMap &map, identitiesData) { IdentityInfo info; info.impl->updateFromMap(map); infoList.append(info); } emit m_parent->identities(infoList); } void AuthServiceImpl::clearReply() { emit m_parent->cleared(); } void AuthServiceImpl::errorReply(const QDBusError &err) { TRACE(); /* Signon specific errors */ if (err.name() == SIGNOND_UNKNOWN_ERR_NAME) { emit m_parent->error(Error(Error::Unknown, err.message())); return; } else if (err.name() == SIGNOND_INTERNAL_SERVER_ERR_NAME) { emit m_parent->error(Error(Error::InternalServer, err.message())); return; } else if (err.name() == SIGNOND_METHOD_NOT_KNOWN_ERR_NAME) { emit m_parent->error(Error(Error::MethodNotKnown, err.message())); return; } else if (err.name() == SIGNOND_INVALID_QUERY_ERR_NAME) { emit m_parent->error(Error(Error::InvalidQuery, err.message())); return; } else if (err.name() == SIGNOND_PERMISSION_DENIED_ERR_NAME) { emit m_parent->error(Error(Error::PermissionDenied, err.message())); return; } /* Qt DBUS specific errors */ if (err.type() != QDBusError::NoError) { emit m_parent->error(Error(Error::InternalCommunication, err.message())); return; } emit m_parent->error(Error(Error::Unknown, err.message())); } signond-nicolasfella/lib/SignOn/authserviceimpl.h0000664000175000017500000000452514615454535022405 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef AUTHSERVICEIMPL_H #define AUTHSERVICEIMPL_H #include #include #include #include #include #include #include #include "async-dbus-proxy.h" #include "authservice.h" namespace SignOn { class IdentityInfo; typedef QList MapList; /*! * @class AuthServiceImpl * AuthService class implementation * @sa AuthService */ class AuthServiceImpl: public QObject { Q_OBJECT Q_DISABLE_COPY(AuthServiceImpl) friend class Identity; friend class AuthService; public: AuthServiceImpl(AuthService *parent); virtual ~AuthServiceImpl(); void queryMethods(); void queryMechanisms(const QString &method); void queryIdentities(const AuthService::IdentityFilter &filter); void clear(); public Q_SLOTS: void errorReply(const QDBusError &err); void queryMechanismsReply(QDBusPendingCallWatcher *call); void queryMechanismsError(const QDBusError &err); void queryIdentitiesReply(QDBusPendingCallWatcher *call); void queryMethodsReply(QDBusPendingCallWatcher *call); void clearReply(); private: void sendRequest(const QString &operation, const char *replySlot, const QList &args = QList()); private: AuthService *m_parent; SignondAsyncDBusProxy m_dbusProxy; QQueue m_methodsForWhichMechsWereQueried; }; } // namespace SignOn Q_DECLARE_METATYPE(SignOn::MapList) #endif /* AUTHSERVICEIMPL_H */ signond-nicolasfella/lib/SignOn/authsession.cpp0000664000175000017500000000420614615454535022075 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include "libsignoncommon.h" #include "authsession.h" #include "authsessionimpl.h" #include "debug.h" namespace SignOn { AuthSession::AuthSession(quint32 id, const QString &methodName, QObject *parent): QObject(parent), impl(new AuthSessionImpl(this, id, methodName)) { initDebug(); qRegisterMetaType("SessionData"); qRegisterMetaType("AuthSession::AuthSessionState"); if (qMetaTypeId() < QMetaType::User) BLAME() << "AuthSession::AuthSession() - " "SessionData meta type not registered."; if (qMetaTypeId() < QMetaType::User) BLAME() << "AuthSession::AuthSession() - " "AuthSessionState meta type not registered."; } AuthSession::~AuthSession() { delete impl; } const QString AuthSession::name() const { return impl->name(); } void AuthSession::queryAvailableMechanisms(const QStringList &wantedMechanisms) { impl->queryAvailableMechanisms(wantedMechanisms); } void AuthSession::process(const SessionData& sessionData, const QString &mechanism) { impl->process(sessionData, mechanism); } void AuthSession::cancel() { impl->cancel(); } } //namespace SignOn signond-nicolasfella/lib/SignOn/authsession.h0000664000175000017500000002542214615454535021545 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef AUTHSESSION_H #define AUTHSESSION_H #include #include #include #include #include #include "libsignoncommon.h" #include "sessiondata.h" #include "signonerror.h" namespace SignOnTests { class AccessControlTest; } namespace SignOn { /*! * @class AuthSession * @headerfile authsession.h SignOn/AuthSession * * Represents a session to authentication plugin/server. * AuthSession is used to maintain connection to authentication plugin. */ class SIGNON_EXPORT AuthSession: public QObject { Q_OBJECT Q_DISABLE_COPY(AuthSession) friend class IdentityImpl; friend class AuthSessionImpl; friend class SignOnTests::AccessControlTest; public: /*! * @enum AuthSessionError * Codes for errors that may be reported by AuthSession objects * @deprecated This enum is deprecated. Replaced by Error::ErrorType. */ enum AuthSessionError { UnknownError = 1, /**< Catch-all for errors not distinguished by another code. */ InternalServerError = 2, /**< Signon Daemon internal error. */ InternalCommunicationError = 3, /**< Communication with Signon Daemon error . */ PermissionDeniedError = 4, /**< The operation cannot be performed due to insufficient client permissions. */ AuthSessionErr = 300, /* placeholder to rearrange enumeration */ MechanismNotAvailableError, /**< The requested mechanism is not available. */ MissingDataError, /**< The SessionData object does not contain necessary information. */ InvalidCredentialsError, /**< The supplied credentials are invalid for the mechanism implementation. */ WrongStateError, /**< An operation method has been called in a wrong state. */ OperationNotSupportedError, /**< The operation is not supported by the mechanism implementation. */ NoConnectionError, /**< No Network connetion. */ NetworkError, /**< Network connetion failed. */ SslError, /**< Ssl connetion failed. */ RuntimeError, /**< Casting SessionData into subclass failed */ CanceledError, /**< Challenge was canceled. */ TimedOutError, /**< Challenge was timed out. */ UserInteractionError /**< User interaction dialog failed */ }; /*! * @enum AuthSessionState * Codes for the states of the AuthSession object. * @see stateChanged(AuthSession::AuthSessionState state, const QString &message) * @todo The order of the states must be synchronized with AuthPluginState enum */ enum AuthSessionState { SessionNotStarted = 0, /**< No message. */ HostResolving, /**< Resolving remote server host name. */ ServerConnecting, /**< Connecting to remote server. */ DataSending, /**< Sending data to remote server. */ ReplyWaiting, /**< Waiting reply from remote server. */ UserPending, /**< Waiting response from user. */ UiRefreshing, /**< Refreshing ui request. */ ProcessPending, /**< Waiting another process to start. */ SessionStarted, /**< Authentication session is started. */ ProcessCanceling, /**< Canceling.current process: is this really needed??? */ ProcessDone, /**< Authentication completed. > */ CustomState, /**< Custom message. */ MaxState, }; protected: /*! * @internal */ AuthSession(quint32 id, const QString &methodName, QObject *parent = 0); ~AuthSession(); public: /*! * Name of method for session * * @return Name of authentication method. */ const QString name() const; /*! * Query list of available mechanisms. If wantedMechanisms list is * provided, only mechanisms available on that list are reported. * List is returned by emitting signal mechanismsAvailable(). * If the operation fails, the error() signal is emitted. * * @see AuthSession::mechanismsAvailable() * @see AuthSession::error() * @param wantedMechanisms List of mechanisms that the client would like to use */ void queryAvailableMechanisms(const QStringList &wantedMechanisms = QStringList()); /*! * Processes sessionData in the authentication service. * The service processes the data and generates a response that * is emitted with response() signal. * If the operation fails, the error() signal is emitted. * * The format and interpretation of the data is * mechanism-specific. The client usually obtains the data * from a network protocol, such as the protocols using SASL. In case * the mechanism implies generation of the authentication token without * a challenge, this method should be called with an empty parameters. * * Parameters are key value pairs, and they are given for authentication * plugin. For example it can contain server name, realm, client key, etc. * If the Identity objected that created this AuthSession object was itself created * using a IdentityInfo object having the username and secret set, that data * is going to be added to the params map before it is passed to a specific * authentication plugin implementation. If credentials have been stored * with Identity::storeCredentials, then the username is overriden from database. * Stored secret is used as a default value. * * @see AuthSession::response() * @see AuthSession::error() * @param sessionData Information for authentication session * @param mechanism Mechanism to use for authentication * * @see IdentityInfo * @see AuthPluginInterface */ void process(const SessionData &sessionData, const QString &mechanism = QString()); /*! * Sends a challenge to the authentication service. * The service processes the challenge and generates a response token that * is emitted with response() signal. * If the operation fails, the error() signal is emitted. * * This is actually a call to process. @see process * * @see AuthSession::response() * @see AuthSession::error() * @param sessionData Information for authentication session * @param mechanism Mechanism to use for authentication */ void challenge(const SessionData& sessionData, const QString &mechanism = QString()) { process(sessionData, mechanism); } /*! * Sends a request to the authentication service. * The service processes the request and generates a response token that * is emitted with response() signal. * If the operation fails, the error() signal is emitted. * * This is actually a call to process. @see process * * @see AuthSession::response() * @see AuthSession::error() * @param sessionData Information for authentication session * @param mechanism Mechanism to use for authentication */ void request(const SessionData &sessionData, const QString &mechanism = QString()) { process(sessionData, mechanism); } /*! * Cancels the ongoing challenge. * Signal error() is emitted with Error::type() Error::SessionCanceled when * process is canceled. * If there is no challenge to cancel, Error::type() is Error::WrongState. * If the operation fails, the error() signal is emitted. * @see AuthSession::error() */ void cancel(); /*! * Signs message by using secret stored into identity. * This convenience interface is to do special challenge to signature service. * @param params Extra information for signing * @param mechanism Mechanism to use for signing * * @deprecated */ void signMessage(const SessionData ¶ms, const QString &mechanism = QString()) { process(params, mechanism); } Q_SIGNALS: /*! * Emitted when an error occurs while performing an operation. * Typical error types are generic errors, where * Error::type() < Error::AuthServiceErr and * AuthSession specific, where * Error::AuthSessionErr < Error::type() < Error::UserErr * @see SignOn::Error * @see SignOn::Error::ErrorType * @param err The error object */ void error(const SignOn::Error &err); /*! * Emitted when the list of available mechanisms have been obtained * for identity. * * @param mechanisms List of available mechanisms */ void mechanismsAvailable(const QStringList &mechanisms); /*! * Authentication response generated by the authentication service. * It is sent after a process() call sends a challenge token for * authentication is used to request an authentication * token, with the response token and accompanying non-opaque information * produced by the service. * * The format and interpretation of the response, as well as * names and types of the information parameters, are mechanism-specific. * * @param sessionData Parameters with the authentication token */ void response(const SignOn::SessionData &sessionData); /*! * Provides the information about the state of the authentication * request. * @param state Current state of the authentication request * @param message Textual description of the state */ void stateChanged(AuthSession::AuthSessionState state, const QString &message); private: class AuthSessionImpl *impl; }; } // namespace SignOn Q_DECLARE_METATYPE(SignOn::AuthSession::AuthSessionState) #endif // AUTHSESSION_H signond-nicolasfella/lib/SignOn/authsessionimpl.cpp0000664000175000017500000002345314615454535022764 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signond/signoncommon.h" #include "authsessionimpl.h" #include "debug.h" #include "libsignoncommon.h" #include #include using namespace SignOn; static QVariantMap sessionData2VariantMap(const SessionData &data) { QVariantMap result; foreach(QString key, data.propertyNames()) { if (!data.getProperty(key).isNull() && data.getProperty(key).isValid()) result[key] = data.getProperty(key); } return result; } AuthSessionImpl::AuthSessionImpl(AuthSession *parent, quint32 id, const QString &methodName, const QString &applicationContext): QObject(parent), m_parent(parent), m_dbusProxy(SIGNOND_AUTH_SESSION_INTERFACE_C, this), m_id(id), m_applicationContext(applicationContext), m_methodName(methodName), m_isAuthInProcessing(false), m_processCall(0) { m_dbusProxy.connect("stateChanged", this, SLOT(stateSlot(int, const QString&))); m_dbusProxy.connect("unregistered", this, SLOT(unregisteredSlot())); QObject::connect(&m_dbusProxy, SIGNAL(objectPathNeeded()), this, SLOT(initInterface())); initInterface(); } AuthSessionImpl::~AuthSessionImpl() { } PendingCall *AuthSessionImpl::send2interface(const QString &operation, const char *slot, const QVariantList &arguments) { return m_dbusProxy.queueCall(operation, arguments, slot, SLOT(errorSlot(const QDBusError&))); } void AuthSessionImpl::setId(quint32 id) { m_id = id; QVariantList arguments; arguments += id; send2interface(QLatin1String("setId"), 0, arguments); } bool AuthSessionImpl::initInterface() { TRACE(); if (m_isAuthInProcessing) return true; m_isAuthInProcessing = true; QLatin1String operation("getAuthSessionObjectPath"); QVariantList arguments; arguments += m_id; arguments += m_applicationContext; arguments += m_methodName; SignondAsyncDBusProxy *authService = new SignondAsyncDBusProxy(SIGNOND_DAEMON_INTERFACE_C, this); authService->setObjectPath(QDBusObjectPath(SIGNOND_DAEMON_OBJECTPATH)); PendingCall *call = authService->queueCall(operation, arguments, SLOT(authenticationSlot(QDBusPendingCallWatcher*)), SLOT(errorSlot(const QDBusError&))); QObject::connect(call, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(deleteServiceProxy())); return true; } QString AuthSessionImpl::name() { return m_methodName; } void AuthSessionImpl::queryAvailableMechanisms(const QStringList &wantedMechanisms) { QLatin1String remoteFunctionName("queryAvailableMechanisms"); QVariantList arguments; arguments += wantedMechanisms; send2interface(remoteFunctionName, SLOT(mechanismsAvailableSlot(QDBusPendingCallWatcher*)), arguments); } void AuthSessionImpl::process(const SessionData &sessionData, const QString &mechanism) { if (m_processCall) { TRACE() << "AuthSession: client is busy"; emit m_parent->error( Error(Error::WrongState, QString(QLatin1String("AuthSession(%1) is busy")) .arg(m_methodName))); return; } QVariantMap sessionDataVa = sessionData2VariantMap(sessionData); QString remoteFunctionName; QVariantList arguments; arguments += sessionDataVa; arguments += mechanism; remoteFunctionName = QLatin1String("process"); m_processCall = send2interface(remoteFunctionName, SLOT(responseSlot(QDBusPendingCallWatcher*)), arguments); Q_EMIT m_parent->stateChanged(AuthSession::ProcessPending, QLatin1String("The request is added " "to queue.")); } void AuthSessionImpl::cancel() { if (m_processCall && m_processCall->cancel()) { emit m_parent->error(Error(Error::SessionCanceled, QLatin1String("Process is canceled."))); } else { send2interface(QLatin1String("cancel"), 0, QVariantList()); } m_processCall = 0; } void AuthSessionImpl::ignoreError(const QDBusError &err) { TRACE() << err; } void AuthSessionImpl::errorSlot(const QDBusError &err) { TRACE() << err; m_processCall = 0; int errCode = Error::Unknown; QString errMessage; if (err.type() != QDBusError::Other) { qCritical() << err.type(); qCritical() << err.name(); qCritical() << err.message(); } else if (err.name() == SIGNOND_SESSION_CANCELED_ERR_NAME) { errCode = Error::SessionCanceled; } else if (err.name() == SIGNOND_TIMED_OUT_ERR_NAME) { errCode = Error::TimedOut; } else if (err.name() == SIGNOND_INVALID_CREDENTIALS_ERR_NAME) { errCode = Error::InvalidCredentials; } else if (err.name() == SIGNOND_NOT_AUTHORIZED_ERR_NAME) { errCode = Error::NotAuthorized; } else if (err.name() == SIGNOND_OPERATION_NOT_SUPPORTED_ERR_NAME) { errCode = Error::OperationNotSupported; } else if (err.name() == SIGNOND_PERMISSION_DENIED_ERR_NAME) { errCode = Error::PermissionDenied; } else if (err.name() == SIGNOND_METHOD_OR_MECHANISM_NOT_ALLOWED_ERR_NAME) { errCode = Error::MethodOrMechanismNotAllowed; } else if (err.name() == SIGNOND_WRONG_STATE_ERR_NAME) { errCode = Error::WrongState; } else if (err.name() == SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_NAME) { errCode = Error::MechanismNotAvailable; } else if (err.name() == SIGNOND_METHOD_NOT_KNOWN_ERR_NAME) { errCode = Error::MethodNotAvailable; } else if (err.name() == SIGNOND_MISSING_DATA_ERR_NAME) { errCode = Error::MissingData; } else if (err.name() == SIGNOND_RUNTIME_ERR_NAME) { errCode = Error::Runtime; } else if (err.name() == SIGNOND_NO_CONNECTION_ERR_NAME) { errCode = Error::NoConnection; } else if (err.name() == SIGNOND_NETWORK_ERR_NAME) { errCode = Error::Network; } else if (err.name() == SIGNOND_SSL_ERR_NAME) { errCode = Error::Ssl; } else if (err.name() == SIGNOND_USER_INTERACTION_ERR_NAME) { errCode = Error::UserInteraction; } else if (err.name() == SIGNOND_OPERATION_FAILED_ERR_NAME) { errCode = Error::OperationFailed; } else if (err.name() == SIGNOND_ENCRYPTION_FAILED_ERR_NAME) { errCode = Error::EncryptionFailure; } else if (err.name() == SIGNOND_TOS_NOT_ACCEPTED_ERR_NAME) { errCode = Error::TOSNotAccepted; } else if (err.name() == SIGNOND_FORGOT_PASSWORD_ERR_NAME) { errCode = Error::ForgotPassword; } else if (err.name() == SIGNOND_INCORRECT_DATE_ERR_NAME) { errCode = Error::IncorrectDate; } else if (err.name() == SIGNOND_USER_ERROR_ERR_NAME){ //the error message comes in as "code:message" bool ok = false; errCode = err.message().section(QLatin1Char(':'), 0, 0).toInt(&ok); errMessage = err.message().section(QLatin1Char(':'), 1, 1); if (!ok) errCode = Error::Unknown; } if (m_isAuthInProcessing) { TRACE() << "Error while registering"; m_isAuthInProcessing = false; m_dbusProxy.setError(err); // Forces a reinitialization of the proxy m_dbusProxy.setObjectPath(QDBusObjectPath()); return; } if (errMessage.isEmpty()) errMessage = err.message(); emit m_parent->error(Error(errCode, errMessage)); } void AuthSessionImpl::authenticationSlot(QDBusPendingCallWatcher *call) { QDBusPendingReply reply = *call; m_dbusProxy.setObjectPath(reply.argumentAt<0>()); m_isAuthInProcessing = false; } void AuthSessionImpl::deleteServiceProxy() { PendingCall *call = qobject_cast(sender()); /* This destroys the AsyncDBusProxy which we created just for registering * the authsession. */ call->parent()->deleteLater(); } void AuthSessionImpl::mechanismsAvailableSlot(QDBusPendingCallWatcher *call) { QDBusPendingReply reply = *call; QStringList mechanisms = reply.argumentAt<0>(); emit m_parent->mechanismsAvailable(mechanisms); } void AuthSessionImpl::responseSlot(QDBusPendingCallWatcher *call) { m_processCall = 0; QDBusPendingReply reply = *call; QVariantMap sessionDataVa = reply.argumentAt<0>(); emit m_parent->response(SessionData(sessionDataVa)); } void AuthSessionImpl::stateSlot(int state, const QString &message) { emit m_parent->stateChanged((AuthSession::AuthSessionState)state, message); } void AuthSessionImpl::unregisteredSlot() { m_dbusProxy.setObjectPath(QDBusObjectPath()); } signond-nicolasfella/lib/SignOn/authsessionimpl.h0000664000175000017500000000552414615454535022430 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef AUTHSESSIONIMPL_H #define AUTHSESSIONIMPL_H #include #include #include #include #include #include #include #include #include #include "async-dbus-proxy.h" #include "authsession.h" #include "dbusinterface.h" namespace SignOn { /*! * @class AuthSessionImpl * AuthSession class implementation. * @sa AuthSession */ class AuthSessionImpl: public QObject { Q_OBJECT Q_DISABLE_COPY(AuthSessionImpl) friend class AuthSession; friend class IdentityImpl; public: AuthSessionImpl(AuthSession *parent, quint32 id, const QString &methodName, const QString &applicationContext = QStringLiteral("*")); ~AuthSessionImpl(); public Q_SLOTS: QString name(); void queryAvailableMechanisms(const QStringList &wantedMechanisms); void process(const SessionData &sessionData, const QString &mechanism); void cancel(); private Q_SLOTS: bool initInterface(); void ignoreError(const QDBusError &err); void errorSlot(const QDBusError &err); void authenticationSlot(QDBusPendingCallWatcher *call); void deleteServiceProxy(); void mechanismsAvailableSlot(QDBusPendingCallWatcher *call); void responseSlot(QDBusPendingCallWatcher *call); void stateSlot(int state, const QString &message); void unregisteredSlot(); private: PendingCall *send2interface(const QString &operation, const char *slot, const QVariantList &arguments); void setId(quint32 id); private: AuthSession *m_parent; SignondAsyncDBusProxy m_dbusProxy; quint32 m_id; QString m_applicationContext; QString m_methodName; /* * flag to prevent multiple authentication requests */ bool m_isAuthInProcessing; /* * Handle to process operation */ QPointer m_processCall; }; } //namespace SignOn #endif //AUTHSESSIONIMPL_H signond-nicolasfella/lib/SignOn/connection-manager.cpp0000664000175000017500000001217714615454535023305 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "connection-manager.h" #include "debug.h" #include "libsignoncommon.h" #include "signond/signoncommon.h" #include #include #include #include #include #include using namespace SignOn; static QPointer connectionInstance = 0; ConnectionManager::ConnectionManager(QObject *parent): QObject(parent), m_connection(QLatin1String("libsignon-qt-invalid")), m_serviceStatus(ServiceStatusUnknown) { if (connectionInstance == 0) { init(); connectionInstance = this; } else { BLAME() << "SignOn::ConnectionManager instantiated more than once!"; } } ConnectionManager::~ConnectionManager() { } ConnectionManager *ConnectionManager::instance() { if (connectionInstance == 0) { connectionInstance = new ConnectionManager; } return connectionInstance; } void ConnectionManager::connect() { if (m_connection.isConnected()) { Q_EMIT connected(m_connection); } else { init(); } } bool ConnectionManager::hasConnection() const { return m_connection.isConnected(); } ConnectionManager::SocketConnectionStatus ConnectionManager::setupSocketConnection() { QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); QLatin1String one("1"); if (environment.value(QLatin1String("SSO_USE_PEER_BUS"), one) != one) { return SocketConnectionUnavailable; } QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); if (runtimeDir.isEmpty()) return SocketConnectionUnavailable; QString socketFileName = QString::fromLatin1("unix:path=%1/" SIGNOND_SOCKET_FILENAME).arg(runtimeDir); static int count = 0; QDBusConnection connection = QDBusConnection::connectToPeer(socketFileName, QString(QLatin1String("libsignon-qt%1")).arg(count++)); if (!connection.isConnected()) { QDBusError error = connection.lastError(); QString name = error.name(); TRACE() << "p2p error:" << error << error.type(); if (name == QLatin1String("org.freedesktop.DBus.Error.FileNotFound") && m_serviceStatus != ServiceActivated) { return SocketConnectionNoService; } else { return SocketConnectionUnavailable; } } m_connection = connection; m_connection.connect(QString(), QLatin1String("/org/freedesktop/DBus/Local"), QLatin1String("org.freedesktop.DBus.Local"), QLatin1String("Disconnected"), this, SLOT(onDisconnected())); return SocketConnectionOk; } void ConnectionManager::init() { if (m_serviceStatus == ServiceActivating) return; SocketConnectionStatus status = setupSocketConnection(); if (status == SocketConnectionNoService) { TRACE() << "Peer connection unavailable, activating service"; QDBusConnectionInterface *interface = QDBusConnection::sessionBus().interface(); QDBusPendingCall call = interface->asyncCall(QLatin1String("StartServiceByName"), SIGNOND_SERVICE, uint(0)); m_serviceStatus = ServiceActivating; QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(onActivationDone(QDBusPendingCallWatcher*))); } else if (status == SocketConnectionUnavailable) { m_connection = SIGNOND_BUS; } if (m_connection.isConnected()) { TRACE() << "Connected to" << m_connection.name(); Q_EMIT connected(m_connection); } } void ConnectionManager::onActivationDone(QDBusPendingCallWatcher *watcher) { QDBusPendingReply<> reply(*watcher); watcher->deleteLater(); if (!reply.isError()) { m_serviceStatus = ServiceActivated; /* Attempt to connect again */ init(); } else { BLAME() << reply.error(); } } void ConnectionManager::onDisconnected() { TRACE() << "Disconnected from daemon"; m_serviceStatus = ServiceStatusUnknown; Q_EMIT disconnected(); } signond-nicolasfella/lib/SignOn/connection-manager.h0000664000175000017500000000401014615454535022735 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_CONNECTION_MANAGER_H #define SIGNON_CONNECTION_MANAGER_H #include #include class QDBusPendingCallWatcher; namespace SignOn { class ConnectionManager: public QObject { Q_OBJECT enum SocketConnectionStatus { SocketConnectionOk = 0, SocketConnectionUnavailable, SocketConnectionNoService }; enum ServiceStatus { ServiceStatusUnknown = 0, ServiceActivating, ServiceActivated }; public: ConnectionManager(QObject *parent = 0); ~ConnectionManager(); static ConnectionManager *instance(); bool hasConnection() const; const QDBusConnection &connection() const { return m_connection; } static const QDBusConnection &get() { return instance()->connection(); } public Q_SLOTS: void connect(); Q_SIGNALS: void connected(const QDBusConnection &connection); void disconnected(); private: SocketConnectionStatus setupSocketConnection(); void init(); private Q_SLOTS: void onActivationDone(QDBusPendingCallWatcher *watcher); void onDisconnected(); private: QDBusConnection m_connection; ServiceStatus m_serviceStatus; }; } #endif // SIGNON_CONNECTION_MANAGER_H signond-nicolasfella/lib/SignOn/dbusinterface.cpp0000664000175000017500000000374314615454535022353 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "dbusinterface.h" #include "debug.h" #include "libsignoncommon.h" #include using namespace SignOn; static bool connIsP2P(const QDBusConnection &connection) { return connection.name().startsWith(QLatin1String("libsignon-qt")); } DBusInterface::DBusInterface(const QString &service, const QString &path, const char *interface, const QDBusConnection &connection, QObject *parent): /* Use empty service name for p2p connections. This is a workaround for * https://bugreports.qt-project.org/browse/QTBUG-32374 */ QDBusAbstractInterface(connIsP2P(connection) ? QLatin1String("") : service, path, interface, connection, parent) { setTimeout(INT_MAX); } DBusInterface::~DBusInterface() { } bool DBusInterface::connect(const char *name, QObject *receiver, const char *slot) { return connection().connect(service(), path(), interface(), QLatin1String(name), receiver, slot); } signond-nicolasfella/lib/SignOn/dbusinterface.h0000664000175000017500000000272714615454535022021 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_DBUSINTERFACE_H #define SIGNON_DBUSINTERFACE_H #include namespace SignOn { /* This is a version of QDBusInterface which doesn't do the blocking * introspection. */ class DBusInterface: public QDBusAbstractInterface { public: DBusInterface(const QString &service, const QString &path, const char *interface, const QDBusConnection &connection, QObject *parent = 0); virtual ~DBusInterface(); bool connect(const char *name, QObject *receiver, const char *slot); }; } #endif // SIGNON_DBUSINTERFACE_H signond-nicolasfella/lib/SignOn/debug.cpp0000664000175000017500000000223614615454535020617 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2015-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "debug.h" #include int libsignon_logging_level = 1; namespace SignOn { void setLoggingLevel(int level) { libsignon_logging_level = level; } void initDebug() { QByteArray loggingLevelVar = qgetenv("LIBSIGNON_LOGGING_LEVEL"); if (!loggingLevelVar.isEmpty()) { setLoggingLevel(loggingLevelVar.toInt()); } } } signond-nicolasfella/lib/SignOn/debug.h0000664000175000017500000000277214615454535020271 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2015-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBSIGNON_DEBUG_H #define LIBSIGNON_DEBUG_H #include #ifdef TRACE #undef TRACE #endif #ifdef BLAME #undef BLAME #endif #ifdef DEBUG_ENABLED extern int libsignon_logging_level; static inline bool debugEnabled() { return libsignon_logging_level >= 2; } static inline bool criticalsEnabled() { return libsignon_logging_level >= 1; } #define TRACE() \ if (debugEnabled()) qDebug() #define BLAME() \ if (criticalsEnabled()) qCritical() #else // DEBUG_ENABLED #define TRACE() while (0) qDebug() #define BLAME() while (0) qDebug() #endif namespace SignOn { void setLoggingLevel(int level); void initDebug(); } #endif // LIBSIGNON_DEBUG_H signond-nicolasfella/lib/SignOn/doc/0000775000175000017500000000000014615454535017567 5ustar coucoufcoucoufsignond-nicolasfella/lib/SignOn/doc/doc.pri0000664000175000017500000000526714615454535021062 0ustar coucoufcoucouf#----------------------------------------------------------------------------- # doc.pri #----------------------------------------------------------------------------- # list of documentation folders to install DOC_FOLDERS = doc/html \ doc/qch # files and folders listed in the installation target's .files section # must exist _before_ qmake generates the Makefile...so, make sure our # documentation target folders exist in the current build folder for( folder, DOC_FOLDERS ) { system( mkdir -p $$(PWD)/$${folder} ) } #----------------------------------------------------------------------------- # extra build targets for generating and cleaning documentation #----------------------------------------------------------------------------- DOC_INPUT += $${_PRO_FILE_PWD_} DOC_INPUT += doc/src # target for generating documentation doctarget.target = docs doctarget.commands = OUTPUT_DIRECTORY=doc \ PROJECT_NAME=\"$${PROJECT_NAME}\" \ PROJECT_NUMBER=\"$${PROJECT_VERSION}\" \ STRIP_FROM_PATH=\"$${_PRO_FILE_PWD_}\" \ INPUT=\"$${DOC_INPUT}\" \ QHP_NAMESPACE=\"com.nokia.example.$${TARGET}\" \ QHP_VIRTUAL_FOLDER=\"$${TARGET}\" \ TAGFILES=\"$$system(pwd)/qt.tags\" \ TAGFILE=\"doc/$${TARGET}.tags\" \ doxygen $$system(pwd)/doxy.conf doctarget.depends = FORCE QMAKE_EXTRA_TARGETS += doctarget # target for cleaning generated documentation doccleantarget.target = cleandocs for( folder, DOC_FOLDERS ) { doccleantarget.commands += rm -r -f $${folder}; } doccleantarget.commands += rm -r -f doc/accounts.tags; doccleantarget.depends = FORCE QMAKE_EXTRA_TARGETS += doccleantarget #----------------------------------------------------------------------------- # installation setup # NOTE: remember to set headers.files before this include to have the headers # properly setup. #----------------------------------------------------------------------------- include( ../../../common-project-config.pri ) include( ../../../common-installs-config.pri ) #----------------------------------------------------------------------------- # Installation target setup for documentation #----------------------------------------------------------------------------- documentation.path = $${INSTALL_PREFIX}/share/doc/libsignon-qt for( folder, DOC_FOLDERS ) { documentation.files += $${folder} } # make sure docs are generated before trying to install anything documentation.depends = docs INSTALLS += documentation message("====") message("==== INSTALLS += documentation") # End of File signond-nicolasfella/lib/SignOn/doc/doxy.conf0000664000175000017500000017336414615454535021437 0ustar coucoufcoucouf# Doxyfile 1.5.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = $(PROJECT_NAME) # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = $(PROJECT_NUMBER) # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = $(OUTPUT_DIRECTORY) # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, # Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = $(STRIP_FROM_PATH) # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = YES # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = $(INPUT) # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.cpp \ *.h \ *.dox # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */.moc/* \ */.obj/* \ */.git/* \ *impl.cpp \ *impl.h \ moc_* \ */tests/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = YES # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = ../qch/signon.qch # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = $(QHP_NAMESPACE) # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = $(QHP_VIRTUAL_FOLDER) # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = qhelpgenerator # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to FRAME, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = ALL # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = $(TAGFILES) # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = $(TAGFILE) # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO # End of File signond-nicolasfella/lib/SignOn/doc/src/0000775000175000017500000000000014615454535020356 5ustar coucoufcoucoufsignond-nicolasfella/lib/SignOn/doc/src/mainpage.dox0000664000175000017500000000350014615454535022651 0ustar coucoufcoucouf/*! \mainpage SignOn client library @section intro Introduction This library, libsignon-qt, is the Single Sign On client library for Qt-based applications. By using this library, an application can authenticate to a (usually remote) service using an existing set of credentials, and operate on the credentials database as well. @section terminology Terminology

A few terms are frequently used in this library APIs, which we'll briefly explain here:

  • Identity: This is a local object representing a record in the credentials DB. It contains information about the username and password (the latter is write-only), plus some metadata such as a descriptive caption, ACL, reference count, and a little more. Identities are referred to in the SSO DB by numeric IDs.
  • Authentication method: the SSO daemon supports different authentication methods, each being provided by a plugin. Well known examples of authentication methods include SASL, OAuth. Authentication methods might support different authentication mechanisms.
  • Authentication session: the process of performing the authentication.
@section classlist List of classes in libsignon-qt Here are the main classes in the libraries. You can also see the complete list of classes. All classes reside in the SignOn namespace.
SignOn::AuthSessionLocal representation of an authentication session. Use this class to perform the authenticaion.
SignOn::IdentityLocal representation of an identity. Use this class to load an existing set of credentials, or to create, edit, delete credentials.
*/ signond-nicolasfella/lib/SignOn/identity.cpp0000664000175000017500000000612714615454535021365 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "debug.h" #include "identityimpl.h" #include "identity.h" #include "securitycontext.h" #include "securitycontextpriv.h" namespace SignOn { Identity::Identity(const quint32 id, QObject *parent): QObject(parent) { initDebug(); qRegisterMetaType("SignOn::Error"); qRegisterMetaType("Error"); qDBusRegisterMetaType(); if (qMetaTypeId() < QMetaType::User) BLAME() << "Identity::Identity() - " "SignOn::Error meta type not registered."; impl = new IdentityImpl(this, id); } Identity *Identity::newIdentity(const IdentityInfo &info, QObject *parent) { Identity *identity = new Identity(SSO_NEW_IDENTITY, parent); identity->impl->copyInfo(info); return identity; } Identity *Identity::existingIdentity(const quint32 id, QObject *parent) { if (id == 0) return NULL; return new Identity(id, parent); } Identity::~Identity() { } quint32 Identity::id() const { return impl->id(); } void Identity::queryAvailableMethods() { impl->queryAvailableMethods(); } AuthSessionP Identity::createSession(const QString &methodName) { if (methodName.isEmpty()) return NULL; return AuthSessionP(impl->createSession(methodName, this)); } void Identity::destroySession(const AuthSessionP &session) { if (session.isNull()) return; impl->destroySession(session.data()); } void Identity::requestCredentialsUpdate(const QString &message) { impl->requestCredentialsUpdate(message); } void Identity::storeCredentials(const IdentityInfo &info) { impl->storeCredentials(info); } void Identity::remove() { impl->remove(); } void Identity::addReference(const QString &reference) { impl->addReference(reference); } void Identity::removeReference(const QString &reference) { impl->removeReference(reference); } void Identity::queryInfo() { impl->queryInfo(); } void Identity::verifyUser(const QString &message) { impl->verifyUser(message); } void Identity::verifyUser(const QVariantMap ¶ms) { impl->verifyUser(params); } void Identity::verifySecret(const QString &secret) { impl->verifySecret(secret); } void Identity::signOut() { impl->signOut(); } } //namespace SignOn signond-nicolasfella/lib/SignOn/identity.h0000664000175000017500000003202314615454535021024 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef IDENTITY_H #define IDENTITY_H #include #include #include #include #include #include #include #include "libsignoncommon.h" #include "authsession.h" #include "identityinfo.h" #include "signonerror.h" #define SSO_NEW_IDENTITY 0 namespace SignOn { typedef QPointer AuthSessionP; /*! * @class Identity * @headerfile identity.h SignOn/Identity * * Represents a database entry for a single identity. * Identity is a client side presentation of a credential. */ class SIGNON_EXPORT Identity: public QObject { Q_OBJECT Q_DISABLE_COPY(Identity) friend class IdentityImpl; public: /*! * @enum IdentityError * Codes for errors that may be reported by Identity objects * @deprecated This enum is deprecated. Replaced by Error::ErrorType. */ enum IdentityError { UnknownError = 1, /**< Catch-all for errors not distinguished by another code. */ InternalServerError = 2, /**< Signon Daemon internal error. */ InternalCommunicationError = 3, /**< Communication with Signon Daemon error . */ PermissionDeniedError = 4, /**< The operation cannot be performed due to insufficient client permissions. */ IdentityErr = 200, /* placeholder to rearrange enumeration. */ MethodNotAvailableError, /**< The requested mechanism is not available. */ NotFoundError, /**< The identity matching this Identity object was not found on the service. */ StoreFailedError, /**< Storing credentials failed. */ RemoveFailedError, /**< Removing credentials failed. */ SignOutFailedError, /**< SignOut failed. */ CanceledError, /**< Operation was canceled by user. */ CredentialsNotAvailableError /**< Query fails*/ }; protected: /*! * @internal */ Identity(const quint32 id = SSO_NEW_IDENTITY, QObject *parent = 0); public: /*! * Constructs a new identity object. * * Can return NULL if client is untrusted. * * @param info Identity information * @param parent Parent object of the identity * @return Pointer to new identity object or NULL if it fails to create. */ static Identity *newIdentity(const IdentityInfo &info = IdentityInfo(), QObject *parent = 0); /*! * Constructs an identity object associated with an existing identity record. * * Can return NULL if client is untrusted. * * @param id Identity ID on the service * @param parent Parent object of the identity * @return Pointer to identity object or NULL if it fails to create. */ static Identity *existingIdentity(const quint32 id, QObject *parent = 0); /*! * Destructor */ virtual ~Identity(); /*! * Unique id of given identity * * @return Identity ID of the identity. For new identity which is not * stored, NEW_IDENTITY is returned. */ quint32 id() const; /*! * Query list of available authentication methods for given identity. * List is returned by emitting signal methodsAvailable(). * If the operation fails, a signal error() is emitted. * @see Identity::error() * If identity is not stored, Error::type() is * Error::CredentialsNotAvailable, or * Error::IdentityNotFound. * @see methodsAvailable(). */ void queryAvailableMethods(); /*! * Creates a new session for authentication. This creates a connection * to authentication plugin. * The Identity object is parent and owner of all created authentication sessions. * * @param methodName Name of authentication method to use * @return New authentication session or NULL if not able to create */ AuthSessionP createSession(const QString &methodName); /*! * Destroys an authentication session. * * @param session Session to be destroyed */ void destroySession(const AuthSessionP &session); /*! * Requests the user to give a new secret into database. * Client can use requestCredentialsUpdate() to launch external * dialog for asking new secret, that will be stored into database. * On success, a signal credentialsStored() is emitted. * If the operation fails, a signal error() is emitted. * If storing changes fails, Error::type() is * Error::StoreFailed, * If user cancels dialog, Error::type() is * Error::IdentityOperationCanceled. * * @see credentialsStored() * @see Identity::error() * @param message Message to be shown for the user */ void requestCredentialsUpdate(const QString &message = QString()); /*! * Stores credential parameters for this authentication identity. * IdentityInfo contains restrictions on methods and mechanisms * for given Identity. @see IdentityInfo * On success, a signal credentialsStored() is emitted. * If the operation fails, a signal error() is emitted. * If storing changes fails, Error::type() is * Error::StoreFailed, * * Untrusted clients may be blocked from performing this operation, * subject to the security framework restrictions. * * If default value is used for the parameter the Identity object * stores the internally stored information, e.g. the IdentityInfo object * used to create a new identity using Identity::newIdentity() * * @see credentialsStored() * @see Identity::error() * @param info Credentials to store */ void storeCredentials(const IdentityInfo &info = IdentityInfo()); /*! * Removes this identity from database. * On success, a signal removed() is emitted * If the operation fails, a signal error() is emitted. * If removing fails, Error::type() is * Error::RemoveFailed, * * Untrusted clients may be blocked from performing this operation, * subject to the security framework restrictions. * @see removed() * @see Identity::error() */ void remove(); /*! * Adds the named reference to identity into the database. * On success, a signal referenceAdded() is emitted * If the operation fails, a signal error() is emitted. * If referencing fails, Error::type() is * Error::StoreFailed, * * Untrusted clients may be blocked from performing this operation, * subject to the security framework restrictions. * @see referenceAdded() * @see Identity::error() */ void addReference(const QString &reference = QString()); /*! * Removes a named reference to identity from the database. * On success, a signal referenceRemoved() is emitted * If the operation fails, a signal error() is emitted. * If dereferencing fails, Error::type() is * Error::ReferenceNotFound, * * Untrusted clients may be blocked from performing this operation, * subject to the security framework restrictions. * @see referenceRemoved() * @see Identity::error() */ void removeReference(const QString &reference = QString()); /*! * Query stored credential parameters for this authentication identity. * On success, a signal info() is emitted with parameters * in the service. * If the operation fails, a signal error() is emitted. * If query fails, Error::type() is * Error::CredentialsNotAvailable, * * Untrusted clients may be blocked from performing this operation, * subject to the security framework restrictions. * @see info() * @see Identity::error() */ void queryInfo(); /*! * Gets a secret verification from the user and compares it to the stored * secret. * This launchs an external dialog for asking secret. * When verification is completed, signal userVerified() is emitted. * If the operation fails, a signal error() is emitted. * If user selects "Forgot Password"-sequence, Error::type() is * Error::ForgotPassword. * * @see userVerified() * @see Identity::error() * @param message Message to be shown for the user */ void verifyUser(const QString &message = QString()); /*! * Gets a secret verification from the user and compares it to the stored * secret. * This launchs an external dialog for asking secret. * When verification is completed, signal userVerified() is emitted. * If the operation fails, a signal error() is emitted. * If user selects "Forgot Password"-sequence, Error::type() is * Error::ForgotPassword. * * @see userVerified() * @see Identity::error() * @param params Dialog customization parameters */ void verifyUser(const QVariantMap ¶ms); /*! * Verifies if the given secret match the stored secret. * When verification is completed, a signal secretVerified() is emitted. * If the operation fails, a signal error() is emitted. * If the credentials are not stored, Error::type() is * Error::CredentialsNotAvailable. * * @see secretVerified() * @see Identity::error() * @param secret String to be verified */ void verifySecret(const QString &secret); /*! * Signs out Identity from all services. All authentication sessions using * this Identity will be invalidated and all tokens cleared from cache. * When sign out is completed, signal signedOut() is emitted. * If the operation fails, a signal error() is emitted. * If signout fails, Error::type() is * Error::SignOutFailed. * * All clients using same identity will receive signedOut signal. * @see signedOut() * @see Identity::error() */ void signOut(); Q_SIGNALS: /*! * Emitted when an error occurs while performing an operation. * Typical error types are generic errors, where * Error::type() < Error::AuthServiceErr and * Identity specific, where * Error::IdentityErr < Error::type() < Error::AuthServiceErr * @see SignOn::Error. * @see SignOn::Error::ErrorType * @param err The error object. */ void error(const SignOn::Error &err); /*! * Emitted when the list of available mechanisms has been obtained * for identity. * * @param methods List of available methods */ void methodsAvailable(const QStringList &methods); /*! * Emitted when credentials passed by storeCredentials() method * have been successfully stored on the service. * @param id Identifier of the credentials that has been stored */ void credentialsStored(const quint32 id); /*! * Emitted when references are added by addReference() * method and change * has been successfully stored on the service. */ void referenceAdded(); /*! * Emitted when references are removed by removeReference() * method and change * has been successfully stored on the service. */ void referenceRemoved(); /*! * Emitted when credentials passed by queryInfo() method * @param info Credentials as have been stored on the service */ void info(const SignOn::IdentityInfo &info); /*! * Emitted when the user verification is completed. * @param valid Is the given secret same as stored */ void userVerified(const bool valid); /*! * Emitted when secret verification is completed. * @param valid Is the given secret same as stored */ void secretVerified(const bool valid); /*! * Emitted when the identity is signed out. */ void signedOut(); /*! * Emitted when the identity is removed. */ void removed(); private: class IdentityImpl *impl; }; } // namespace SignOn #endif /* IDENTITY_H */ signond-nicolasfella/lib/SignOn/identityimpl.cpp0000664000175000017500000004267614615454535022260 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include "signond/signoncommon.h" #include "debug.h" #include "libsignoncommon.h" #include "identityimpl.h" #include "identityinfo.h" #include "identityinfoimpl.h" #include "authsessionimpl.h" #include "signonerror.h" #define SIGNOND_AUTH_SESSION_CANCEL_TIMEOUT 5000 //ms using namespace SignOn; /* Keep these aligned with the State enum */ static const char *stateNames[] = { "PendingRegistration", "NeedsRegistration", "NeedsUpdate", "PendingUpdate", "Removed", "Ready", }; static QString stateName(IdentityImpl::State state) { return QLatin1String((state < IdentityImpl::LastState) ? stateNames[state] : "Unknown"); } IdentityImpl::IdentityImpl(Identity *parent, const quint32 id): QObject(parent), m_parent(parent), m_identityInfo(new IdentityInfo), m_dbusProxy(SIGNOND_IDENTITY_INTERFACE_C, this), m_tmpIdentityInfo(NULL), m_state(NeedsRegistration), m_infoQueried(true), m_methodsQueried(false), m_signOutRequestedByThisIdentity(false) { m_dbusProxy.connect("infoUpdated", this, SLOT(infoUpdated(int))); m_dbusProxy.connect("unregistered", this, SLOT(remoteObjectDestroyed())); QObject::connect(&m_dbusProxy, SIGNAL(objectPathNeeded()), this, SLOT(sendRegisterRequest())); m_identityInfo->setId(id); sendRegisterRequest(); } IdentityImpl::~IdentityImpl() { if (m_identityInfo) delete m_identityInfo; if (m_tmpIdentityInfo) delete m_tmpIdentityInfo; if (!m_authSessions.empty()) foreach (AuthSession *session, m_authSessions) destroySession(session); } void IdentityImpl::updateState(State state) { TRACE() << "Updating state: " << stateName(state) << this; m_state = state; switch (state) { case NeedsUpdate: updateContents(); break; default: break; } } void IdentityImpl::copyInfo(const IdentityInfo &info) { *m_identityInfo->impl = *info.impl; } quint32 IdentityImpl::id() const { return m_identityInfo->id(); } AuthSession *IdentityImpl::createSession(const QString &methodName, QObject *parent) { foreach (AuthSession *authSession, m_authSessions) { if (authSession->name() == methodName) { qWarning() << QString::fromLatin1( "Authentication session for method " "`%1` already requested.").arg(methodName); return 0; } } AuthSession *session = new AuthSession(id(), methodName, parent); m_authSessions.append(session); return session; } void IdentityImpl::destroySession(AuthSession *session) { session->blockSignals(true); m_authSessions.removeOne(session); session->deleteLater(); } void IdentityImpl::queryAvailableMethods() { TRACE() << "Querying available identity authentication methods."; if (!checkRemoved()) return; if (m_state == Ready) { emit m_parent->methodsAvailable(m_identityInfo->methods()); return; } m_methodsQueried = true; updateContents(); } void IdentityImpl::requestCredentialsUpdate(const QString &message) { TRACE() << "Requesting credentials update."; if (!checkRemoved()) return; QVariantList args; args << message; m_dbusProxy.queueCall(QLatin1String("requestCredentialsUpdate"), args, SLOT(storeCredentialsReply(QDBusPendingCallWatcher*)), SLOT(errorReply(const QDBusError&))); } void IdentityImpl::storeCredentials(const IdentityInfo &info) { TRACE() << "Storing credentials"; if (m_state == Removed) { updateState(NeedsRegistration); } const IdentityInfo *localInfo = info.impl->isEmpty() ? m_identityInfo : &info; if (localInfo->impl->isEmpty()) { emit m_parent->error( Error(Error::StoreFailed, QLatin1String("Invalid Identity data."))); return; } QVariantList args; QVariantMap map = localInfo->impl->toMap(); map.insert(SIGNOND_IDENTITY_INFO_ID, m_identityInfo->id()); args << map; m_dbusProxy.queueCall(QLatin1String("store"), args, SLOT(storeCredentialsReply(QDBusPendingCallWatcher*)), SLOT(errorReply(const QDBusError&))); } void IdentityImpl::remove() { TRACE() << "Removing credentials."; /* If the Identity is not stored, it makes no sense to request a removal * -- this condition could be removed; there is the case when there is an * ongoing store operation. */ if (id() != SIGNOND_NEW_IDENTITY) { m_dbusProxy.queueCall(QLatin1String("remove"), QVariantList(), SLOT(removeReply()), SLOT(errorReply(const QDBusError&))); } else { emit m_parent->error(Error(Error::IdentityNotFound, QLatin1String("Remove request failed. The " "identity is not stored"))); } } void IdentityImpl::addReference(const QString &reference) { TRACE() << "Adding reference to identity"; if (!checkRemoved()) return; m_dbusProxy.queueCall(QLatin1String("addReference"), QVariantList() << QVariant(reference), SLOT(addReferenceReply()), SLOT(errorReply(const QDBusError&))); } void IdentityImpl::removeReference(const QString &reference) { TRACE() << "Removing reference from identity"; if (!checkRemoved()) return; m_dbusProxy.queueCall(QLatin1String("removeReference"), QVariantList() << QVariant(reference), SLOT(removeReferenceReply()), SLOT(errorReply(const QDBusError&))); } void IdentityImpl::queryInfo() { TRACE() << "Querying info."; if (!checkRemoved()) return; if (m_state == Ready) { emit m_parent->info(IdentityInfo(*m_identityInfo)); return; } m_infoQueried = true; updateContents(); } void IdentityImpl::verifyUser(const QString &message) { QVariantMap params; params.insert(QLatin1String("QueryMessage"), message); verifyUser(params); } void IdentityImpl::verifyUser(const QVariantMap ¶ms) { TRACE() << "Verifying user."; if (!checkRemoved()) return; m_dbusProxy.queueCall(QLatin1String("verifyUser"), QVariantList() << params, SLOT(verifyUserReply(QDBusPendingCallWatcher*)), SLOT(errorReply(const QDBusError&))); } void IdentityImpl::verifySecret(const QString &secret) { TRACE(); if (!checkRemoved()) return; m_dbusProxy.queueCall(QLatin1String("verifySecret"), QVariantList() << QVariant(secret), SLOT(verifySecretReply(QDBusPendingCallWatcher*)), SLOT(errorReply(const QDBusError&))); } void IdentityImpl::signOut() { TRACE() << "Signing out."; if (!checkRemoved()) return; /* if this is a stored identity, inform server about signing out so that other client identity objects having the same id will be able to perform the operation. */ if (id() != SIGNOND_NEW_IDENTITY) { m_dbusProxy.queueCall(QLatin1String("signOut"), QVariantList(), SLOT(signOutReply()), SLOT(errorReply(const QDBusError&))); m_signOutRequestedByThisIdentity = true; } clearAuthSessionsCache(); } void IdentityImpl::clearAuthSessionsCache() { while (!m_authSessions.empty()) { AuthSession *session = m_authSessions.takeFirst(); connect(session, SIGNAL(error(const SignOn::Error &)), this, SLOT(authSessionCancelReply(const SignOn::Error &))); session->cancel(); QTimer::singleShot(SIGNOND_AUTH_SESSION_CANCEL_TIMEOUT, session, SLOT(deleteLater())); } } void IdentityImpl::authSessionCancelReply(const SignOn::Error &err) { TRACE() << "CANCEL SESSION REPLY"; bool deleteTheSender = false; switch (err.type()) { /* fall trough */ case Error::SessionCanceled: case Error::WrongState: deleteTheSender = true; break; default: break; } if (deleteTheSender) { QObject *sender = QObject::sender(); if (sender) { TRACE() << "DELETING SESSION"; sender->deleteLater(); } } } void IdentityImpl::storeCredentialsReply(QDBusPendingCallWatcher *call) { QDBusPendingReply reply = *call; quint32 id = reply.argumentAt<0>(); TRACE() << "stored id:" << id << "old id:" << this->id(); if (m_tmpIdentityInfo) { *m_identityInfo = *m_tmpIdentityInfo; delete m_tmpIdentityInfo; m_tmpIdentityInfo = NULL; } if (id != this->id()) { m_identityInfo->setId(id); foreach (AuthSession *session, m_authSessions) session->impl->setId(id); } emit m_parent->credentialsStored(id); } void IdentityImpl::removeReply() { m_identityInfo->impl->clear(); updateState(Removed); emit m_parent->removed(); } void IdentityImpl::addReferenceReply() { emit m_parent->referenceAdded(); } void IdentityImpl::removeReferenceReply() { emit m_parent->referenceRemoved(); } void IdentityImpl::getInfoReply(QDBusPendingCallWatcher *call) { QDBusPendingReply reply = *call; QVariantMap infoData = reply.argumentAt<0>(); TRACE() << infoData; updateCachedData(infoData); updateState(Ready); if (m_infoQueried) { Q_EMIT m_parent->info(IdentityInfo(*m_identityInfo)); m_infoQueried = false; } if (m_methodsQueried) { Q_EMIT m_parent->methodsAvailable(m_identityInfo->methods()); m_methodsQueried = false; } } void IdentityImpl::verifyUserReply(QDBusPendingCallWatcher *call) { QDBusPendingReply reply = *call; bool valid = reply.argumentAt<0>(); emit m_parent->userVerified(valid); } void IdentityImpl::verifySecretReply(QDBusPendingCallWatcher *call) { QDBusPendingReply reply = *call; bool valid = reply.argumentAt<0>(); emit m_parent->secretVerified(valid); } void IdentityImpl::signOutReply() { emit m_parent->signedOut(); } void IdentityImpl::infoUpdated(int state) { const char *stateStr; switch ((IdentityState)state) { /* Data updated on the server side. */ case IdentityDataUpdated: updateState(NeedsUpdate); stateStr = "NeedsUpdate"; break; /* Data removed on the server side. */ case IdentityRemoved: updateState(Removed); stateStr = "Removed"; break; /* A remote client identity signed out, thus server informed this object to do the same */ case IdentitySignedOut: //if this is not the identity that requested the signing out if (!m_signOutRequestedByThisIdentity) { clearAuthSessionsCache(); emit m_parent->signedOut(); } stateStr = "SignedOut"; break; default: stateStr = "Unknown"; break; } TRACE() << "SERVER INFO UPDATED." << stateStr << QString(QLatin1String(" %1 ")).arg(id()); } void IdentityImpl::errorReply(const QDBusError& err) { TRACE() << err; /* Signon specific errors */ if (err.name() == SIGNOND_UNKNOWN_ERR_NAME) { emit m_parent->error(Error(Error::Unknown, err.message())); return; } else if (err.name() == SIGNOND_INTERNAL_SERVER_ERR_NAME) { emit m_parent->error(Error(Error::InternalServer, err.message())); return; } else if (err.name() == SIGNOND_PERMISSION_DENIED_ERR_NAME) { emit m_parent->error(Error(Error::PermissionDenied, err.message())); return; } else if (err.name() == SIGNOND_ENCRYPTION_FAILED_ERR_NAME) { emit m_parent->error(Error(Error::EncryptionFailure, err.message())); return; } else if (err.name() == SIGNOND_METHOD_NOT_AVAILABLE_ERR_NAME) { emit m_parent->error(Error(Error::MethodNotAvailable, err.message())); return; } else if (err.name() == SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME) { emit m_parent->error(Error(Error::IdentityNotFound, err.message())); return; } else if (err.name() == SIGNOND_STORE_FAILED_ERR_NAME) { emit m_parent->error(Error(Error::StoreFailed, err.message())); if (m_tmpIdentityInfo) { delete m_tmpIdentityInfo; m_tmpIdentityInfo = NULL; } return; } else if (err.name() == SIGNOND_REMOVE_FAILED_ERR_NAME) { emit m_parent->error(Error(Error::RemoveFailed, err.message())); return; } else if (err.name() == SIGNOND_SIGNOUT_FAILED_ERR_NAME) { emit m_parent->error(Error(Error::SignOutFailed, err.message())); return; } else if (err.name() == SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME) { emit m_parent->error(Error(Error::IdentityOperationCanceled, err.message())); return; } else if (err.name() == SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME) { emit m_parent->error(Error(Error::CredentialsNotAvailable, err.message())); return; } else if (err.name() == SIGNOND_REFERENCE_NOT_FOUND_ERR_NAME) { emit m_parent->error(Error(Error::ReferenceNotFound, err.message())); return; } else if (err.name() == SIGNOND_FORGOT_PASSWORD_ERR_NAME) { emit m_parent->error(Error(Error::ForgotPassword, err.message())); return; } else { if (m_state == this->PendingRegistration) updateState(NeedsRegistration); TRACE() << "Non internal SSO error reply."; } /* Qt DBUS specific errors */ if (err.type() != QDBusError::NoError) { emit m_parent->error(Error(Error::InternalCommunication, err.message())); return; } emit m_parent->error(Error(Error::Unknown, err.message())); } void IdentityImpl::updateContents() { m_dbusProxy.queueCall(QLatin1String("getInfo"), QVariantList(), SLOT(getInfoReply(QDBusPendingCallWatcher*)), SLOT(errorReply(const QDBusError&))); updateState(PendingUpdate); } bool IdentityImpl::sendRegisterRequest() { if (m_state == PendingRegistration) return true; QVariantList args; QString registerMethodName = QLatin1String("registerNewIdentity"); if (id() != SIGNOND_NEW_IDENTITY) { registerMethodName = QLatin1String("getIdentity"); args << m_identityInfo->id(); } /* TODO: implement the application security context */ args << QLatin1String("*"); SignondAsyncDBusProxy *authService = new SignondAsyncDBusProxy(SIGNOND_DAEMON_INTERFACE_C, this); authService->setObjectPath(QDBusObjectPath(SIGNOND_DAEMON_OBJECTPATH)); PendingCall *call = authService->queueCall(registerMethodName, args, SLOT(registerReply(QDBusPendingCallWatcher*)), SLOT(errorReply(const QDBusError&))); QObject::connect(call, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(deleteServiceProxy())); updateState(PendingRegistration); return true; } void IdentityImpl::updateCachedData(const QVariantMap &infoData) { m_identityInfo->impl->updateFromMap(infoData); } void IdentityImpl::registerReply(QDBusPendingCallWatcher *call) { QVariantList arguments = call->reply().arguments(); if (arguments.count() > 1) { QDBusArgument info = arguments.at(1).value(); updateCachedData(qdbus_cast(info)); } m_dbusProxy.setObjectPath(arguments.at(0).value()); updateState(Ready); } void IdentityImpl::deleteServiceProxy() { PendingCall *call = qobject_cast(sender()); /* This destroys the AsyncDBusProxy which we created just for registering * the identity. */ call->parent()->deleteLater(); } void IdentityImpl::remoteObjectDestroyed() { TRACE(); m_dbusProxy.setObjectPath(QDBusObjectPath()); updateState(NeedsRegistration); } bool IdentityImpl::checkRemoved() { if (m_state == Removed) { Q_EMIT m_parent->error(Error(Error::IdentityNotFound, QLatin1String("Removed from database."))); return false; } return true; } signond-nicolasfella/lib/SignOn/identityimpl.h0000664000175000017500000001041014615454535021702 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef IDENTITYIMPL_H #define IDENTITYIMPL_H #include #include #include #include #include #include #include #include #include #include "async-dbus-proxy.h" #include "libsignoncommon.h" #include "identity.h" #include "dbusinterface.h" namespace SignOn { class IdentityInfo; /*! * @class IdentityImpl * Identity class implementation. * @sa Identity */ class IdentityImpl: public QObject { Q_OBJECT Q_DISABLE_COPY(IdentityImpl) friend class Identity; public: enum State { PendingRegistration = 0, /* Ongoing registration */ NeedsRegistration, /* Remote object not created or destroyed */ NeedsUpdate, /* Remote data changed */ PendingUpdate, /* Update in progress */ Removed, /* Removed from database */ Ready, /* Ready for querying locally cached data, or any remote operation */ LastState }; IdentityImpl(Identity *parent, const quint32 id = 0); ~IdentityImpl(); quint32 id() const; AuthSession *createSession(const QString &methodName, QObject *parent = 0); void destroySession(AuthSession *session); public Q_SLOTS: void errorReply(const QDBusError &err); void storeCredentialsReply(QDBusPendingCallWatcher *call); void removeReply(); void addReferenceReply(); void removeReferenceReply(); void getInfoReply(QDBusPendingCallWatcher *call); void verifyUserReply(QDBusPendingCallWatcher *call); void verifySecretReply(QDBusPendingCallWatcher *call); void signOutReply(); void infoUpdated(int); void remoteObjectDestroyed(); private Q_SLOTS: bool sendRegisterRequest(); void queryAvailableMethods(); void requestCredentialsUpdate(const QString &message = QString()); void storeCredentials(const IdentityInfo &info); void remove(); void addReference(const QString &reference = QString()); void removeReference(const QString &reference = QString()); void queryInfo(); void verifyUser(const QString &message = QString()); void verifyUser(const QVariantMap ¶ms); void verifySecret(const QString &secret); void signOut(); void authSessionCancelReply(const SignOn::Error &err); void registerReply(QDBusPendingCallWatcher *call); void deleteServiceProxy(); private: void copyInfo(const IdentityInfo &info); void updateState(State state); bool checkRemoved(); void updateContents(); void updateCachedData(const QVariantMap &infoData); void clearAuthSessionsCache(); private: Identity *m_parent; IdentityInfo *m_identityInfo; SignondAsyncDBusProxy m_dbusProxy; /* Cache info in the storing case, so that if the storing succeeds, server * side does not have to send succesfully stored data over IPC channel. */ IdentityInfo *m_tmpIdentityInfo; State m_state; QList m_authSessions; /* This flag tells the queryInfo() reply slot to emit the info() signal */ bool m_infoQueried; /* This flag tells the queryInfo() reply slot to emit the * methodsAvailable() signal */ bool m_methodsQueried; /* Marks this Identity as the one which requested the sign out */ bool m_signOutRequestedByThisIdentity; }; } // namespace SignOn #endif /* IDENTITYIMPL_H */ signond-nicolasfella/lib/SignOn/identityinfo.cpp0000664000175000017500000001147514615454535022243 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include "debug.h" #include "libsignoncommon.h" #include "identityinfo.h" #include "identityinfoimpl.h" #include "identity.h" namespace SignOn { IdentityInfo::IdentityInfo(): impl(new IdentityInfoImpl) { qRegisterMetaType("SignOn::IdentityInfo"); if (qMetaTypeId() < QMetaType::User) BLAME() << "IdentityInfo::IdentityInfo() - " "IdentityInfo meta type not registered."; } IdentityInfo::IdentityInfo(const IdentityInfo &other): impl(new IdentityInfoImpl) { *impl = *other.impl; } IdentityInfo &IdentityInfo::operator=(const IdentityInfo &other) { *impl = *other.impl; return *this; } IdentityInfo::IdentityInfo(const QString &caption, const QString &userName, const QMap &methods): impl(new IdentityInfoImpl) { impl->setCaption(caption); impl->setUserName(userName); impl->setMethods(methods); } IdentityInfo::~IdentityInfo() { if (impl) delete impl; impl = 0; } void IdentityInfo::setId(const quint32 id) { impl->setId(id); } quint32 IdentityInfo::id() const { return impl->id(); } void IdentityInfo::setUserName(const QString &userName) { impl->setUserName(userName); } const QString IdentityInfo::userName() const { return impl->userName(); } void IdentityInfo::setCaption(const QString &caption) { impl->setCaption(caption); } const QString IdentityInfo::caption() const { return impl->caption(); } void IdentityInfo::setRealms(const QStringList &realms) { impl->setRealms(realms); } QStringList IdentityInfo::realms() const { return impl->realms(); } void IdentityInfo::setOwner(const QString &ownerToken) { impl->setOwners(QStringList() << ownerToken); } QString IdentityInfo::owner() const { return impl->owners().value(0); } void IdentityInfo::setAccessControlList(const QStringList &accessControlList) { SecurityContextList list; for (const QString &sysCtx: accessControlList) { list.append(SecurityContext(sysCtx, QLatin1String("*"))); } impl->setAccessControlList(list); } QStringList IdentityInfo::accessControlList() const { SecurityContextList accessControlList = impl->accessControlList(); QStringList list; for (const SecurityContext &secCtx: accessControlList) { list.append(secCtx.systemContext()); } return list; } void IdentityInfo::setAccessControlList(const SecurityContextList &accessControlList) { impl->setAccessControlList(accessControlList); } SecurityContextList IdentityInfo::accessControlListFull() const { return impl->accessControlList(); } QString IdentityInfo::secret() const { return impl->secret(); } void IdentityInfo::setSecret(const QString &secret, const bool storeSecret) { impl->setSecret(secret); impl->setStoreSecret(storeSecret); } bool IdentityInfo::isStoringSecret() const { return impl->storeSecret(); } void IdentityInfo::setStoreSecret(const bool storeSecret) { impl->setStoreSecret(storeSecret); } void IdentityInfo::setMethod(const MethodName &method, const MechanismsList &mechanismsList) { impl->updateMethod(method, mechanismsList); } void IdentityInfo::removeMethod(const MethodName &method) { impl->removeMethod(method); } void IdentityInfo::setType(IdentityInfo::CredentialsType type) { impl->setType(type); } IdentityInfo::CredentialsType IdentityInfo::type() const { return impl->type(); } QList IdentityInfo::methods() const { return impl->methods().keys(); } MechanismsList IdentityInfo::mechanisms(const MethodName &method) const { return impl->methods().value(method, QStringList()); } void IdentityInfo::setRefCount(qint32 refCount) { /* This method is a mistake, let's keep it for binary compatibility as a * no-op. */ Q_UNUSED(refCount); } qint32 IdentityInfo::refCount() const { return impl->refCount(); } } //namespace SignOn signond-nicolasfella/lib/SignOn/identityinfo.h0000664000175000017500000002346714615454535021714 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef IDENTITY_INFO_H #define IDENTITY_INFO_H #include #include #include "libsignoncommon.h" #include "securitycontext.h" namespace SignOn { /*! * @typedef QString MethodName * Defines a string as an authentication method. */ typedef QString MethodName; /*! * @typedef QStringList MechanismsList * Defines a string list as a list of mechanisms. */ typedef QStringList MechanismsList; /*! * @typedef QList SecurityContextList * Defines a list of security contexts. */ typedef QList SecurityContextList; /*! * @class IdentityInfo * @headerfile identityinfo.h SignOn/IdentityInfo * * Contains identity information. This information is stored into database. * @see queryIdentities() */ class SIGNON_EXPORT IdentityInfo { friend class AuthServiceImpl; friend class IdentityImpl; public: /*! * @enum CredentialsType * Values used to describe the type of the identity * @attention Mixed types, i.e Application|Web are not yet supported. Just * single types work for the time being. */ enum CredentialsType { Other = 0, Application = 1 << 0, Web = 1 << 1, Network = 1 << 2 }; public: /*! * Creates a new empty IdentityInfo object. */ IdentityInfo(); /*! * Copy constructor */ IdentityInfo(const IdentityInfo &other); /*! * Assignment operator */ IdentityInfo &operator=(const IdentityInfo &other); /*! * Creates a new IdentityInfo object with given values. * @param caption Description of identity * @param userName Username * @param methods Allowed methods for identity */ IdentityInfo(const QString &caption, const QString &userName, const QMap &methods); /*! * Destructor */ ~IdentityInfo(); /*! * Sets the numeric identifier for the credentials record. * Calling this method makes only sense when handling the * Identity::credentialsStored() signal. * @param id The numeric identifier of the credentials. */ void setId(const quint32 id); /*! * Returns the identity identifier. * @return Identifier for the identity */ quint32 id() const; /*! * Sets the secret. When performing a challenge on the owner Identity object, * if the secret is set on its corresponding IdentityInfo, it will be added * to the parameter list that is passed to the corresponding authentication * plugin challenge implementation. By default a newly created IdentityInfo * does not contain a secret and has a policy of not storing any. If the * secret is set the default policy will be to store it. This behaviour can * also be set with IdentityInfo::setStoreSecret(). * * @see PluginInterface::secretKey * @see PluginInterface::challenge * @param secret * @param storeSecret Whether the secret is stored or not */ void setSecret(const QString &secret, const bool storeSecret = true); /*! * Gets the secret. If this object was retrieved from the database, the * returned secret might be an empty string. * @return The secret, when allowed, or an empty string. */ QString secret() const; /*! * Returns whether secret is to be stored. * @return true Whether the secret is being stored or not. */ bool isStoringSecret() const; /*! * Sets whether the secret is stored or not. * @param storeSecret Whether the secret must be stored in the DB. */ void setStoreSecret(const bool storeSecret); /*! * Sets the username. * * @see userNameKey * @param userName Username */ void setUserName(const QString &userName); /*! * Returns the username. * @return Username for the identity */ const QString userName() const; /*! * Sets a human readable caption of the identity * @param caption Caption */ void setCaption(const QString &caption); /*! * Returns a human-readable representation of the identity. * @return Human-readable representation of the identity. */ const QString caption() const; /*! * Sets the realms, e.g. URL's with which the Identity using this * IdentityInfo shall work with. * * @param realms List of the realms to be set. */ void setRealms(const QStringList &realms); /*! * Gets the realms, e.g. URL's with which the Identity using this * IdentityInfo works with. * * @return List of supported realms. */ QStringList realms() const; /*! * Sets application token that owns identity, therefore defining the * applications that will be able to modify this specific set of credentials * * @param ownerToken owner token */ void setOwner(const QString &ownerToken); /*! * Gets the owner application token that is defining the applications * that are able to modify this specific set of credentials. * * @attention This is accessible only to the owner application. * * @return The access control token which defines the applications * allowed to modify this set of credentials. */ QString owner() const; /*! * Sets the list of access control system tokens, therefore * defining the applications that will be able to access this specific * set of credentials. * * @param accessControlList List of access control system tokens */ void setAccessControlList(const QStringList &accessControlList); /*! * Sets the list of access control tokens, therefore defining the * applications that will be able to access this specific set of * credentials. * * @param accessControlList List of access control tokens */ void setAccessControlList(const SecurityContextList &accessControlList); /*! * Gets the list of access control system tokens defining the * applications that are able to access this specific set of credentials. * * @attention This is accessible only to the owner application. * * @return The access control system tokens which defines the * applications allowed to access this set of credentials. */ QStringList accessControlList() const; /*! * Gets the list of access control application tokens defining the * applications that are able to access this specific set of credentials. * * @attention This is accessible only to the owner application. * * @return The access control tokens which defines the applications allowed * to access this set of credentials. */ SecurityContextList accessControlListFull() const; /*! * Sets the method into identity info. * If the given method is not included, a new one will be added. If it is * already set, the mechanism list assosiated to it is updated. an empty * list will clear the mechanisms. * These values are used to limit Identity to use the specified methods and * mechanisms. * @param method Method name to change * @param mechanismsList list of mechanisms that are allowed */ void setMethod(const MethodName &method, const MechanismsList &mechanismsList); /*! * Removes a method from identity info. * @param method Method name to remove */ void removeMethod(const MethodName &method); /*! * Sets the type into identity info. * The type is used to generically identify where this identity is being * used. * * @attention If this method is not called, the IdentityInfo type will * default to SignOn::OtherIdentity. * * @param type Type we want to assign to this IdentityInfo */ void setType(CredentialsType type); /*! * Retrieves the identity type from identity info. * @return The identity type for this IdentityInfo */ CredentialsType type() const; /*! * Lists all methods in identity info. * @return Param method method name to remove. */ QList methods() const; /*! * Lists the all mechanisms for certain method in identity info. * @param method Method name to list mechanisms * @return List of mechanisms */ MechanismsList mechanisms(const MethodName &method) const; /*! * Sets the refcount into identity info. * The type is used to generically identify where this identity is being * used. * * @note Server can restrict changes to differ +-1 from previous. * * @param refCount Set refcount */ void setRefCount(qint32 refCount); /*! * Retrieves the refcount from identity info. * @return Refcount for this IdentityInfo */ qint32 refCount() const; private: class IdentityInfoImpl *impl; }; } // namespace SignOn Q_DECLARE_METATYPE(SignOn::IdentityInfo) #endif /* IDENTITY_INFO_H */ signond-nicolasfella/lib/SignOn/identityinfoimpl.cpp0000664000175000017500000000552614615454535023125 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "debug.h" #include "identityinfoimpl.h" #include "identityinfo.h" #include "securitycontext.h" #include "securitycontextpriv.h" #include #include #include namespace SignOn { IdentityInfoImpl::IdentityInfoImpl(): QVariantMap() { qDBusRegisterMetaType(); qDBusRegisterMetaType(); } IdentityInfoImpl::~IdentityInfoImpl() { } void IdentityInfoImpl::updateMethod(const MethodName &method, const MechanismsList &mechanismsList) { MethodMap methodMap = methods(); methodMap.insert(method, mechanismsList); setMethods(methodMap); } void IdentityInfoImpl::removeMethod(const MethodName &method) { MethodMap methodMap = methods(); if (methodMap.contains(method)) { methodMap.remove(method); setMethods(methodMap); } } bool IdentityInfoImpl::hasMethod(const MethodName &method) const { return methods().contains(method); } void IdentityInfoImpl::updateFromMap(const QVariantMap &map) { clear(); /* We just need to expand any QDBusArguments which might be present, since * the map is likely to be coming from QDBus. */ QVariantMap::const_iterator i; for (i = map.constBegin(); i != map.constEnd(); i++) { if (qstrcmp(i.value().typeName(), "QDBusArgument") == 0) { QDBusArgument container = i.value().value(); if (i.key() == SIGNOND_IDENTITY_INFO_AUTHMETHODS) { MethodMap methodMap = qdbus_cast(container); setMethods(methodMap); } else if (i.key() == SIGNOND_IDENTITY_INFO_ACL) { SecurityContextList list = qdbus_cast(container); setAccessControlList(list); } else { BLAME() << "Found unsupported QDBusArgument in key" << i.key(); } } else { insert(i.key(), i.value()); } } } } //namespace SignOn signond-nicolasfella/lib/SignOn/identityinfoimpl.h0000664000175000017500000001024014615454535022557 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef IDENTITYINFOIMPL_H #define IDENTITYINFOIMPL_H #include "QtCore/qglobal.h" #include #include #include "identityinfo.h" #include "signond/signoncommon.h" namespace SignOn { typedef QMap MethodMap; /*! * @class IdentityInfoImpl * IdentityInfo class implementation. * @sa IdentityInfo */ class IdentityInfoImpl: public QVariantMap { friend class IdentityInfo; friend class IdentityImpl; public: IdentityInfoImpl(); ~IdentityInfoImpl(); void setId(quint32 id) { insert(SIGNOND_IDENTITY_INFO_ID, id); } quint32 id() const { return value(SIGNOND_IDENTITY_INFO_ID, 0).toUInt(); } void setUserName(const QString &userName) { insert(SIGNOND_IDENTITY_INFO_USERNAME, userName); } QString userName() const { return value(SIGNOND_IDENTITY_INFO_USERNAME).toString(); } void setCaption(const QString &caption) { insert(SIGNOND_IDENTITY_INFO_CAPTION, caption); } QString caption() const { return value(SIGNOND_IDENTITY_INFO_CAPTION).toString(); } void setMethods(const MethodMap &methods) { insert(SIGNOND_IDENTITY_INFO_AUTHMETHODS, QVariant::fromValue(methods)); } MethodMap methods() const { return value(SIGNOND_IDENTITY_INFO_AUTHMETHODS).value(); } void setRealms(const QStringList &realms) { insert(SIGNOND_IDENTITY_INFO_REALMS, realms); } QStringList realms() const { return value(SIGNOND_IDENTITY_INFO_REALMS).toStringList(); } void setOwners(const QStringList &owners) { insert(SIGNOND_IDENTITY_INFO_OWNER, owners); } QStringList owners() const { return value(SIGNOND_IDENTITY_INFO_OWNER).toStringList(); } void setAccessControlList(const SecurityContextList &accessControlList) { insert(SIGNOND_IDENTITY_INFO_ACL, QVariant::fromValue(accessControlList)); } SecurityContextList accessControlList() const { return value(SIGNOND_IDENTITY_INFO_ACL).value(); } void setSecret(const QString &secret) { insert(SIGNOND_IDENTITY_INFO_SECRET, secret); } QString secret() const { return value(SIGNOND_IDENTITY_INFO_SECRET).toString(); } void setStoreSecret(bool storeSecret) { insert(SIGNOND_IDENTITY_INFO_STORESECRET, storeSecret); } bool storeSecret() const { return value(SIGNOND_IDENTITY_INFO_STORESECRET).toBool(); } void updateMethod(const MethodName &method, const MechanismsList &mechanismsList); void removeMethod(const MethodName &method); void setType(IdentityInfo::CredentialsType type) { insert(SIGNOND_IDENTITY_INFO_TYPE, quint32(type)); } IdentityInfo::CredentialsType type() const { quint32 typeUInt = value(SIGNOND_IDENTITY_INFO_TYPE).toUInt(); return IdentityInfo::CredentialsType(typeUInt); } qint32 refCount() const { return value(SIGNOND_IDENTITY_INFO_REFCOUNT).toInt(); } bool hasMethod(const MethodName &method) const; QVariantMap toMap() const { return *this; } void updateFromMap(const QVariantMap &map); }; } //namespace SignOn Q_DECLARE_METATYPE(SignOn::MethodMap) #endif // IDENTITYINFOIMPL_H signond-nicolasfella/lib/SignOn/libsignon-qt-shared.pro0000664000175000017500000000012114615454535023410 0ustar coucoufcoucoufinclude(libsignon-qt.pri) CONFIG += shared QMAKE_CXXFLAGS += -fvisibility=hidden signond-nicolasfella/lib/SignOn/libsignon-qt-static.pro0000664000175000017500000000005414615454535023436 0ustar coucoufcoucoufinclude(libsignon-qt.pri) CONFIG += static signond-nicolasfella/lib/SignOn/libsignon-qt.pc.in0000664000175000017500000000051414615454535022361 0ustar coucoufcoucoufprefix=$$INSTALL_PREFIX exec_prefix=${prefix} libdir=$$INSTALL_LIBDIR includedir=${prefix}/include Name: libsignon-qt Description: Client library for the Single Sign On daemon, Qt bindings. Version: $$PROJECT_VERSION Libs: -L${libdir} -lsignon-qt Requires: QtCore Cflags: -I${includedir}/signon-qt -I${includedir}/signon-qt/SignOn signond-nicolasfella/lib/SignOn/libsignon-qt5.pc.in0000664000175000017500000000052214615454535022445 0ustar coucoufcoucoufprefix=$$INSTALL_PREFIX exec_prefix=${prefix} libdir=$$INSTALL_LIBDIR includedir=${prefix}/include Name: libsignon-qt5 Description: Client library for the Single Sign On daemon, Qt5 bindings. Version: $$PROJECT_VERSION Libs: -L${libdir} -lsignon-qt5 Requires: Qt5Core Cflags: -I${includedir}/signon-qt5 -I${includedir}/signon-qt5/SignOn signond-nicolasfella/lib/SignOn/libsignoncommon.h0000664000175000017500000000232314615454535022370 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2015-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef LIBSIGNONCOMMON_H #define LIBSIGNONCOMMON_H #ifdef SIGNON_EXPORT #undef SIGNON_EXPORT #endif #if __GNUC__ >= 4 #define SIGNON_EXPORT __attribute__ ((visibility("default"))) #endif #ifndef SIGNON_EXPORT #define SIGNON_EXPORT #endif #endif // LIBSIGNONCOMMON_H signond-nicolasfella/lib/SignOn/securitycontext.cpp0000664000175000017500000000453714615454535023013 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2018 elementary, Inc * * Contact: Corentin Noël * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include "debug.h" #include "securitycontext.h" #include "securitycontextpriv.h" namespace SignOn { SecurityContext::SecurityContext() { } SecurityContext::SecurityContext(const QString &systemContext, const QString &applicationContext): m_systemContext(systemContext), m_applicationContext(applicationContext) { } QDBusArgument &operator<<(QDBusArgument &argument, const SecurityContext &securityContext) { argument.beginStructure(); argument << securityContext.systemContext() << securityContext.applicationContext(); argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, SecurityContext &securityContext) { QString systemContext; QString applicationContext; argument.beginStructure(); argument >> systemContext >> applicationContext; securityContext.setSystemContext(systemContext); securityContext.setApplicationContext(applicationContext); argument.endStructure(); return argument; } void SecurityContext::setSystemContext(const QString &systemContext) { m_systemContext = systemContext; } QString SecurityContext::systemContext() const { return m_systemContext; } void SecurityContext::setApplicationContext(const QString &applicationContext) { m_applicationContext = applicationContext; } QString SecurityContext::applicationContext() const { return m_applicationContext; } } // namespace SignOn signond-nicolasfella/lib/SignOn/securitycontext.h0000664000175000017500000000460514615454535022454 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2018 elementary, Inc * * Contact: Corentin Noël * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBSIGNON_SECURITY_CONTEXT_H #define LIBSIGNON_SECURITY_CONTEXT_H #include #include #include "libsignoncommon.h" namespace SignOn { /*! * @class SecurityContext * @headerfile securitycontext.h SignOn/SecurityContext * * Contains access security context information. * @see accessControlListFull() */ class SIGNON_EXPORT SecurityContext { public: /*! * Creates a new SecurityContext object. */ SecurityContext(); /*! * Creates a new SecurityContext object. * @param systemContext * @param applicationContext */ SecurityContext(const QString &systemContext, const QString &applicationContext); /*! * Sets the system context. * * @param systemContext */ void setSystemContext(const QString &systemContext); /*! * Gets the system context. * @return The system context, or an empty string. */ QString systemContext() const; /*! * Sets the application context. * * @param applicationContext */ void setApplicationContext(const QString &applicationContext); /*! * Gets the application context. * @return The application context, or an empty string. */ QString applicationContext() const; private: QString m_systemContext; QString m_applicationContext; }; /*! * @typedef QList SecurityContextList * Defines a list of security contexts. */ typedef QList SecurityContextList; } // namespace SignOn Q_DECLARE_METATYPE(SignOn::SecurityContext) #endif /* LIBSIGNON_SECURITY_CONTEXT_H */ signond-nicolasfella/lib/SignOn/securitycontextpriv.h0000664000175000017500000000240714615454535023353 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2018 elementary, Inc * * Contact: Corentin Noël * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef LIBSIGNON_SECURITY_CONTEXT_PRIV_H #define LIBSIGNON_SECURITY_CONTEXT_PRIV_H #include #include "securitycontext.h" namespace SignOn { QDBusArgument &operator<<(QDBusArgument &argument, const SecurityContext &securityContext); const QDBusArgument &operator>>(const QDBusArgument &argument, SecurityContext &securityContext); } //namespace SignOn #endif /* LIBSIGNON_SECURITY_CONTEXT_PRIV_H */ signond-nicolasfella/lib/SignOn/sessiondata.h0000664000175000017500000001732514615454535021520 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ /*! * @todo move this to a common includes folder. * This is part of the plugin development kit, too. */ #ifndef SESSIONDATA_H #define SESSIONDATA_H #include #include #include #include #include namespace SignOn { /*! * A macro to create declarations for parameter setter and getter. * This supports the same types as @see QVariant. * For user specified types @see QMetaType. * * @param type_ Type of parameter * @param name_ Name of property */ #define SIGNON_SESSION_DECLARE_PROPERTY(type_, name_) \ void set##name_(const type_ &value ) { m_data.insert(QLatin1String(#name_), value); } \ type_ name_() const { return m_data.value(QLatin1String(#name_)).value(); } /*! * Property which holds the access control tokens that the requesting * application has. * @note to be used by the plugins developers only. */ #define SSO_ACCESS_CONTROL_TOKENS QLatin1String("AccessControlTokens") /*! * @enum SignonUiPolicy * Policy to define how the plugin interacts with the user. * This is a hint for plugin how to handle user interaction. * NoUserInteractionPolicy does not allow any ui interaction to happen * and plugin will get error reply QUERY_ERROR_FORBIDDEN. * @see UiPolicy */ enum SignonUiPolicy { DefaultPolicy = 0, /**< Plugin can decide when to show ui. */ RequestPasswordPolicy, /**< Force user to enter password. */ NoUserInteractionPolicy, /**< No ui elements are shown to user. */ ValidationPolicy, /**< UI elements can be shown to the user only when captcha-like security measures are required */ }; /*! * @class SessionData * @headerfile sessiondata.h SignOn/SessionData * * Data container to hold values for authentication session. * Inherit this class if you want to extend the property range. * * * @warning All this class' definitions must be inline. */ class SIGNON_EXPORT SessionData { public: /*! * Constructor. Creates a SessionData with data 'data'. * @param data The data to be contained by the SessionData * @attention internal use only recommended. As a SSO client application * developer use setters/gettters for specific SessionData properties. */ SessionData(const QVariantMap &data = QVariantMap()) { m_data = data; } /*! * Copy constructor. * @param other SessionData object to be copied to this instance */ SessionData(const SessionData &other) { m_data = other.m_data; } /*! * Assignment operator * @param other SessionData object to be assigned to this instance * @return Reference to this object */ SessionData &operator=(const SessionData &other) { m_data = other.m_data; return *this; } /*! * Addition operator * @param other SessionData object to be added to this instance. * @return reference to this object */ SessionData &operator+=(const SessionData &other) { for (auto it = other.m_data.constBegin(), itEnd = other.m_data.constEnd(); it != itEnd; ++it) { m_data[it.key()] = it.value(); } return *this; } /*! * Access the list of runtime existing properties of the SessionData. * @return String list containing the property names */ const QStringList propertyNames() const { return m_data.keys(); } /*! * Access the list of runtime existing properties of the SessionData. * @param propertyName Name of the property to be accessed * @return Variant containing the property value of propertyName, or an * empty variant if property does not exist at runtime. */ const QVariant getProperty(const QString &propertyName) const { return m_data.value(propertyName, QVariant()); } /*! * Gets the access control tokens that the requesting application has. * @note to be used by the plugins developers only. */ QStringList getAccessControlTokens() const { return getProperty(SSO_ACCESS_CONTROL_TOKENS).toStringList(); } /*! * Creates an instance of type T, which must be derived from SessionData. * The instance will contain the data of this instance. * @return Instance of type T, containing the data of this instance. */ template T data() const { T dataImpl; dataImpl.m_data = m_data; return dataImpl; } /*! * Gets the QVariantMap of session parameters. * @return A map of the session parameters. */ QVariantMap toMap() const { return m_data; } /*! * Declares the property Secret setter and getter. * setSecret(const QString secret); * const QString Secret() const; */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Secret) /*! * Declares the property UserName setter and getter. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, UserName) /*! * Declares the property Realm setter and getter. * Realm that is used for authentication. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Realm) /*! * Declares the property NetworkProxy setter and getter. * Network proxy to be used instead of system default. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, NetworkProxy) /*! * Declares the property UiPolicy setter and getter. * Use UiPolicy to define how plugin interacts with the user. * @see SignonUiPolicy */ SIGNON_SESSION_DECLARE_PROPERTY(int, UiPolicy) /*! * Declares the property Caption setter and getter. * Caption is to tell user which application/credentials/provider is * requesting signon-ui. * * @note Caption is taken from database if not defined by application * or authentication plugin. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Caption) /*! * Declares the property NetworkTimeout setter and getter. * Sets the timeout for network related operations in milliseconds. * To be used when a remote service does not reply in a reasonable amount * of time. */ SIGNON_SESSION_DECLARE_PROPERTY(quint32, NetworkTimeout) /*! * Declares the property WindowId setter and getter. * This is to be used for setting signon-ui dialog application modal. */ SIGNON_SESSION_DECLARE_PROPERTY(quint32, WindowId) /*! * Declares the property RenewToken setter and getter. * This is used by a signon plugin to check whether * the access token has to be renewed. When this * property is set, the signon plugin will remove the * old set of access tokens and get a new set. */ SIGNON_SESSION_DECLARE_PROPERTY(bool, RenewToken) protected: QVariantMap m_data; }; } //namespace SignOn Q_DECLARE_METATYPE(SignOn::SessionData) #endif // SESSIONDATA_H signond-nicolasfella/lib/SignOn/signon.h0000664000175000017500000000173414615454535020475 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef _USE_SIGNON_H_ #define _USE_SIGNON_H_ #include "authservice.h" #include "identity.h" #endif //_USE_SIGNON_H_ signond-nicolasfella/lib/SignOn/signonerror.h0000664000175000017500000001725114615454535021550 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNONERROR_H #define SIGNONERROR_H #ifdef SIGNON_INTERNAL #include #endif #include #include #include namespace SignOn { /*! * @class Error Base object definition for Signon error handling. * Extend this class' error range in order to provide custom error handling. * * @attention All this class' definitions must be inline. */ class SIGNON_EXPORT Error #ifdef SIGNON_INTERNAL : public QObject { Q_OBJECT #else { #endif public: /*! * @enum ErrorType Error codes for all the Signon by default supported * errors. * Plugin developers should use the predefined error types in the * AuthSessionErr and UserErr interval, and in the case of extended error * handling values greater than UserErr. * @attention Error types lesser than Error::UserErr are reserved. */ enum ErrorType { Unknown = 1, /**< Catch-all for errors not distinguished by another code. */ InternalServer = 2, /**< Signon Daemon internal error. */ InternalCommunication = 3, /**< Communication with Signon Daemon error. */ PermissionDenied = 4, /**< The operation cannot be performed due to insufficient client permissions. */ EncryptionFailure, /**< Failure during data encryption/decryption. */ AuthServiceErr = 100, /* Placeholder to rearrange enumeration - AuthService specific */ MethodNotKnown, /**< The method with this name is not found. */ ServiceNotAvailable, /**< The service is temporarily unavailable. */ InvalidQuery, /**< Parameters for the query are invalid. */ IdentityErr = 200, /* Placeholder to rearrange enumeration - Identity specific */ MethodNotAvailable, /**< The requested method is not available. */ IdentityNotFound, /**< The identity matching this Identity object was not found on the service. */ StoreFailed, /**< Storing credentials failed. */ RemoveFailed, /**< Removing credentials failed. */ SignOutFailed, /**< SignOut failed. */ IdentityOperationCanceled, /**< Identity operation was canceled by user. */ CredentialsNotAvailable, /**< Query failed. */ ReferenceNotFound, /**< Trying to remove nonexistent reference. */ AuthSessionErr = 300, /* Placeholder to rearrange enumeration - AuthSession/AuthPluginInterface specific */ MechanismNotAvailable, /**< The requested mechanism is not available. */ MissingData, /**< The SessionData object does not contain necessary information. */ InvalidCredentials, /**< The supplied credentials are invalid for the mechanism implementation. */ NotAuthorized, /**< Authorization failed. */ WrongState, /**< An operation method has been called in a wrong state. */ OperationNotSupported, /**< The operation is not supported by the mechanism implementation. */ NoConnection, /**< No Network connetion. */ Network, /**< Network connetion failed. */ Ssl, /**< Ssl connection failed. */ Runtime, /**< Casting SessionData into subclass failed */ SessionCanceled, /**< Challenge was cancelled. */ TimedOut, /**< Challenge was timed out. */ UserInteraction, /**< User interaction dialog failed */ OperationFailed, /**< Temporary failure in authentication. */ EncryptionFailed, /**< @deprecated Failure during data encryption/decryption. */ TOSNotAccepted, /**< User declined Terms of Service. */ ForgotPassword, /**< User requested reset password sequence. */ MethodOrMechanismNotAllowed, /**< Method or mechanism not allowed for this identity. */ IncorrectDate, /**< Date time incorrect on device. */ UserErr = 400 /* Placeholder to rearrange enumeration - User space specific */ }; /*! * Constructor */ Error() : m_type((int)Unknown), m_message(QString()) { registerType(); } /*! * Copy constructor * @param src Error object to be copied */ Error(const Error &src) : #ifdef SIGNON_INTERNAL QObject(), #endif m_type(src.type()), m_message(src.message()) {} /*! * For convenience constructor * @param type Type of the error * @param message Error message */ Error(int type, const QString &message = QString()): m_type(type), m_message(message) { registerType(); } /*! * Assignment operator * @param src Error object to be assigned to this instance */ Error &operator=(const Error &src) { m_type = src.type(); m_message = src.message(); return *this; } /*! * Destructor */ virtual ~Error() {} /*! * Sets the type of the error. * The 'type' parameter is an integer and values beyond Error::ErrorType * can be used for customized error reporting. * @see Error::ErrorType. * @param type The type to be set */ void setType(int type) { m_type = type; } /*! * Sets the error message. * @param message The message to be set */ void setMessage(const QString &message) { m_message = message; } /*! * @return Type of the error */ int type() const { return m_type; } /*! * @return Error message */ QString message() const { return m_message; } private: inline void registerType(); private: int m_type; QString m_message; }; } //namespace SignOn Q_DECLARE_METATYPE(SignOn::Error) void SignOn::Error::registerType() { qRegisterMetaType("SignOn::Error"); } #endif // SIGNONERROR_H signond-nicolasfella/lib/SignOn/SignOnQt5Config.cmake.in0000664000175000017500000000060314615454547023350 0ustar coucoufcoucouf# SIGNONQT_INCLUDE_DIRS - The libsignon-qt include directories # SIGNONQT_LIBRARIES - The libraries needed to use libsignon-qt # SIGNONQT_LIBRARIES_STATIC - The static version of libsignon-qt set(SIGNONQT_LIBRARIES $${INSTALL_LIBDIR}/lib$${TARGET}.so) set(SIGNONQT_LIBRARIES_STATIC $${INSTALL_LIBDIR}/lib$${TARGET}.a) set(SIGNONQT_INCLUDE_DIRS $${INSTALL_PREFIX}/include/$${TARGET}) signond-nicolasfella/lib/SignOn/SignOnQt6Config.cmake.in0000664000175000017500000000060314615454547023351 0ustar coucoufcoucouf# SIGNONQT_INCLUDE_DIRS - The libsignon-qt include directories # SIGNONQT_LIBRARIES - The libraries needed to use libsignon-qt # SIGNONQT_LIBRARIES_STATIC - The static version of libsignon-qt set(SIGNONQT_LIBRARIES $${INSTALL_LIBDIR}/lib$${TARGET}.so) set(SIGNONQT_LIBRARIES_STATIC $${INSTALL_LIBDIR}/lib$${TARGET}.a) set(SIGNONQT_INCLUDE_DIRS $${INSTALL_PREFIX}/include/$${TARGET}) signond-nicolasfella/lib/SignOn/SignOnQt6ConfigVersion.cmake.in0000664000175000017500000000100014615454547024707 0ustar coucoufcoucoufset(PACKAGE_VERSION $${PROJECT_VERSION}) if(\"${PACKAGE_VERSION}\" VERSION_LESS \"${PACKAGE_FIND_VERSION}\" ) set(PACKAGE_VERSION_COMPATIBLE FALSE) else(\"${PACKAGE_VERSION}\" VERSION_LESS \"${PACKAGE_FIND_VERSION}\" ) set(PACKAGE_VERSION_COMPATIBLE TRUE) if( \"${PACKAGE_FIND_VERSION}\" STREQUAL \"${PACKAGE_VERSION}\") set(PACKAGE_VERSION_EXACT TRUE) endif( \"${PACKAGE_FIND_VERSION}\" STREQUAL \"${PACKAGE_VERSION}\") endif(\"${PACKAGE_VERSION}\" VERSION_LESS \"${PACKAGE_FIND_VERSION}\" ) signond-nicolasfella/lib/SignOn/libsignon-qt.pri0000664000175000017500000000337514615454547022157 0ustar coucoufcoucoufinclude( ../../common-project-config.pri ) include( ../../common-vars.pri ) TEMPLATE = lib TARGET = signon-qt$${QT_MAJOR_VERSION} # Input public_headers += \ sessiondata.h \ identityinfo.h \ authservice.h \ identity.h \ authsession.h \ libsignoncommon.h \ securitycontext.h \ signon.h \ signonerror.h private_headers = authserviceimpl.h \ async-dbus-proxy.h \ authsessionimpl.h \ connection-manager.h \ dbusinterface.h \ debug.h \ identityimpl.h \ identityinfoimpl.h \ securitycontextpriv.h HEADERS = $$public_headers \ $$private_headers INCLUDEPATH += . \ .. \ $$TOP_SRC_DIR/include SOURCES += identityinfo.cpp \ async-dbus-proxy.cpp \ authservice.cpp \ authserviceimpl.cpp \ authsession.cpp \ authsessionimpl.cpp \ connection-manager.cpp \ dbusinterface.cpp \ debug.cpp \ identity.cpp \ identityimpl.cpp \ identityinfoimpl.cpp \ securitycontext.cpp QT += core \ dbus CONFIG += \ build_all \ link_pkgconfig DEFINES += \ QT_NO_CAST_TO_ASCII \ QT_NO_CAST_FROM_ASCII include( $$TOP_SRC_DIR/common-installs-config.pri ) headers.files = $$public_headers \ AuthService \ AuthSession \ Error \ Identity \ IdentityInfo \ SecurityContext \ SessionData headers.path = $${INSTALL_PREFIX}/include/$${TARGET}/SignOn INSTALLS += headers pkgconfig.files = lib$${TARGET}.pc include($${TOP_SRC_DIR}/common-pkgconfig.pri) INSTALLS += pkgconfig QMAKE_SUBSTITUTES += $${CMAKE_BASENAME}Config.cmake.in \ $${CMAKE_BASENAME}ConfigVersion.cmake.in cmake_modules.files = $${CMAKE_BASENAME}Config.cmake \ $${CMAKE_BASENAME}ConfigVersion.cmake cmake_modules.path = $${CMAKE_CONFIG_PATH} INSTALLS += cmake_modules signond-nicolasfella/lib/SignOn/libsignon-qt6.pc.in0000664000175000017500000000052214615454547022451 0ustar coucoufcoucoufprefix=$$INSTALL_PREFIX exec_prefix=${prefix} libdir=$$INSTALL_LIBDIR includedir=${prefix}/include Name: libsignon-qt6 Description: Client library for the Single Sign On daemon, Qt6 bindings. Version: $$PROJECT_VERSION Libs: -L${libdir} -lsignon-qt6 Requires: Qt6Core Cflags: -I${includedir}/signon-qt6 -I${includedir}/signon-qt6/SignOn signond-nicolasfella/lib/lib.pro0000664000175000017500000000006514615454535017116 0ustar coucoufcoucoufTEMPLATE = subdirs SUBDIRS = signond SignOn plugins signond-nicolasfella/lib/plugins/0000775000175000017500000000000014615454547017311 5ustar coucoufcoucoufsignond-nicolasfella/lib/plugins/SignOn/0000775000175000017500000000000014615454547020506 5ustar coucoufcoucoufsignond-nicolasfella/lib/plugins/SignOn/AuthPluginInterface0000664000175000017500000000004214615454535024323 0ustar coucoufcoucouf#include signond-nicolasfella/lib/plugins/SignOn/UiSessionData0000664000175000017500000000004314615454535023136 0ustar coucoufcoucouf#include signond-nicolasfella/lib/plugins/SignOn/signonplugincommon.h0000664000175000017500000000317214615454535024604 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNONPLUGIN_H #define SIGNONPLUGIN_H #include #include #include #include #include "SignOn/sessiondata.h" #include "SignOn/uisessiondata.h" #ifdef SIGNON_PLUGIN_TRACE #include #ifdef DEBUG_ENABLED #ifdef TRACE #undef TRACE #endif #ifdef BLAME #undef BLAME #endif #define TRACE() qDebug() << __FILE__ << __LINE__ << __func__ #define BLAME() qCritical() << __FILE__ << __LINE__ << __func__ #else #define TRACE() while (0) qDebug() #define BLAME() while (0) qCritical() #endif #endif #endif // SIGNONPLUGIN_H signond-nicolasfella/lib/plugins/SignOn/uisessiondata.h0000664000175000017500000002034414615454535023532 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef UISESSIONDATA_H #define UISESSIONDATA_H #include /*! * Error codes for ui interaction. */ namespace SignOn { enum QueryError { QUERY_ERROR_NONE = 0, /**< No errors. */ QUERY_ERROR_GENERAL, /**< Generic error during interaction. */ QUERY_ERROR_NO_SIGNONUI, /**< Cannot send request to signon-ui. */ QUERY_ERROR_BAD_PARAMETERS, /**< Signon-Ui cannot create dialog based on the given UiSessionData. */ QUERY_ERROR_CANCELED, /**< User canceled action. Plugin should not retry automatically after this. */ QUERY_ERROR_NOT_AVAILABLE, /**< Requested ui is not available. For example browser cannot be started. */ QUERY_ERROR_BAD_URL, /**< Given url was not valid. */ QUERY_ERROR_BAD_CAPTCHA, /**< Given captcha image was not valid. */ QUERY_ERROR_BAD_CAPTCHA_URL, /**< Given url for capctha loading was not valid. */ QUERY_ERROR_REFRESH_FAILED, /**< Refresh failed. */ QUERY_ERROR_FORBIDDEN, /**< Showing ui forbidden by ui policy. */ QUERY_ERROR_FORGOT_PASSWORD, /**< User pressed forgot password. */ QUERY_ERROR_NETWORK, /**< Network error. */ QUERY_ERROR_SSL, /**< SSL error. */ }; /*! * Predefined messages to be shown to user while querying input. */ enum QueryMessageId { QUERY_MESSAGE_EMPTY = 0, /**< No predefined message. */ QUERY_MESSAGE_LOGIN, /**< Login without prior errors. */ QUERY_MESSAGE_NOT_AUTHORIZED /**< Authentication failed. */ //TODO add more messages }; /*! * @class UiSessionData * Data container to hold values for authentication session. * Inherit this class if you want to extend the property range. * * @warning All this class' definitions must be inline. */ class UiSessionData : public SessionData { public: /*! * Constructor. Creates a UiSessionData with data 'data'. * @param data The data to be contained by the UiSessionData * @attention internal use only recommended. As a SSO client application * developer use setters/gettters for specific SessionData properties. */ UiSessionData(const QVariantMap &data = QVariantMap()) { m_data = data; } /*! * Declares the property QueryError setter and getter. * QueryError is used to report errors in ui interaction * that is shown to user. * @see QueryError */ SIGNON_SESSION_DECLARE_PROPERTY(int, QueryErrorCode) /*! * Declare the property Caption setter and getter. * Caption is used to set credentials caption. * Empty caption is discarded. * @warning This string is shown to user as it is, * plugin is responsible for localization. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Caption) /*! * Declare the property Title setter and getter. * Title is used to set dialog title for password confirmation. * @warning This string is shown to user as it is. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Title) /*! * Declares the property QueryMessageId setter and getter. * QueryMessageId is used to select predefined localized message * that is shown to user. * @see QueryMessageId */ SIGNON_SESSION_DECLARE_PROPERTY(int, QueryMessageId) /*! * Declares the property QueryMessage setter and getter. * QueryMessage is used to show given message to user. * Empty message is discarded. * @warning This string is shown to user as it is, * plugin is responsible for localization. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, QueryMessage) /*! * Declares the property QueryUserName setter and getter. * QueryUserName is used to enable username input in signon-ui. */ SIGNON_SESSION_DECLARE_PROPERTY(bool, QueryUserName) /*! * Declares the property QueryPassword setter and getter. * QueryPassword is used to enable password input in signon-ui. */ SIGNON_SESSION_DECLARE_PROPERTY(bool, QueryPassword) /*! * Declares the property RememberPassword setter and getter. * RememberPassword is used to enable password storing signond. */ SIGNON_SESSION_DECLARE_PROPERTY(bool, RememberPassword) /*! * Declares the property ShowRealm setter and getter. * ShowRealm is used to show realm in signon-ui. */ SIGNON_SESSION_DECLARE_PROPERTY(bool, ShowRealm) /*! * Declares the property OpenUrl setter and getter. * This url is passed to signon-ui to be opened and shown to user. * Empty url does not open the url view. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, OpenUrl) /*! * Declares the property FinalUrl setter and getter. * If this URL is set, the signon-ui browser widget will close * automatically when this URL is reached. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, FinalUrl) /*! * Declares the property UrlResponse setter and getter. * Response from signon-ui for OpenUrl request. * After completion UrlResponse contains redirect target url, if there was * redirection. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, UrlResponse) /*! * Declares the property CaptchaUrl setter and getter. * CaptchaUrl contains url to the captcha image to be verified by user. * CaptchaUrl is used in signon-ui when plugin requires the captcha * verification from user. * If this is empty, captcha query is not shown, unless CaptchaImage * contain valid image. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, CaptchaUrl) /*! * Declares the property CaptchaImage setter and getter. * CaptchaImage contains the captcha image to be verified by user. * CaptchaImage is passed to signon-ui when plugin requires the captcha * verification from user. * If this is empty, captcha query is not shown, unless CaptchaUrl point to * valid image. */ SIGNON_SESSION_DECLARE_PROPERTY(QByteArray, CaptchaImage) /*! * Declares the property CaptchaResponse setter and getter * CaptchaResponse is passed to plugin after signon-ui has processed the * captcha query. * It contains user input for captcha query. * @see CaptchaUrl * @see CaptchaImage. */ SIGNON_SESSION_DECLARE_PROPERTY(QString, CaptchaResponse) /*! * Declares the property ForgotPassword setter and getter * ForgotPassword string is shown as a link to user. * @see ForgotPasswordUrl */ SIGNON_SESSION_DECLARE_PROPERTY(QString, ForgotPassword) /*! * Declares the property ForgotPasswordUrl setter and getter * ForgotPasswordUrl is shown to user if ForgotPassword link is pressed. * @see ForgotPassword */ SIGNON_SESSION_DECLARE_PROPERTY(QString, ForgotPasswordUrl) /*! * Declares the property Confirm setter and getter * This will set dialog to confirm password mode. * @see ForgotPasswordUrl */ SIGNON_SESSION_DECLARE_PROPERTY(bool, Confirm) /*! * Declares the property Icon setter and getter * Icon is shown to user in signin dialog. * @see ForgotPassword */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Icon) }; } //namespace SignOn Q_DECLARE_METATYPE(SignOn::UiSessionData) #endif // UISESSIONDATA_H signond-nicolasfella/lib/plugins/SignOn/uisessiondata_priv.h0000664000175000017500000001131614615454535024571 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef UISESSIONDATA_PRIV_H #define UISESSIONDATA_PRIV_H #define SSOUI_KEY_ERROR QLatin1String("QueryErrorCode") #define SSOUI_KEY_CAPTION QLatin1String("Caption") #define SSOUI_KEY_MESSAGEID QLatin1String("QueryMessageId") #define SSOUI_KEY_MESSAGE QLatin1String("QueryMessage") #define SSOUI_KEY_ERROR_MESSAGE QLatin1String("ErrorMessage") #define SSOUI_KEY_QUERYUSERNAME QLatin1String("QueryUserName") #define SSOUI_KEY_USERNAME QLatin1String("UserName") #define SSOUI_KEY_USERNAME_TEXT QLatin1String("UserNameText") #define SSOUI_KEY_QUERYPASSWORD QLatin1String("QueryPassword") #define SSOUI_KEY_PASSWORD QLatin1String("Secret") #define SSOUI_KEY_PASSWORD_TEXT QLatin1String("PasswordText") #define SSOUI_KEY_REMEMBER QLatin1String("RememberPassword") /* 2 factor authentication field */ #define SSOUI_KEY_QUERY2FA QLatin1String("Query2fa") #define SSOUI_KEY_2FA QLatin1String("2fa") #define SSOUI_KEY_2FA_TEXT QLatin1String("2faText") /* Text for the login button */ #define SSOUI_KEY_LOGIN_TEXT QLatin1String("LoginText") #define SSOUI_KEY_SHOWREALM QLatin1String("ShowRealm") #define SSOUI_KEY_REALM QLatin1String("Realm") #define SSOUI_KEY_NETWORKPROXY QLatin1String("NetworkProxy") #define SSOUI_KEY_UIPOLICY QLatin1String("UiPolicy") #define SSOUI_KEY_OPENURL QLatin1String("OpenUrl") #define SSOUI_KEY_FINALURL QLatin1String("FinalUrl") #define SSOUI_KEY_URLRESPONSE QLatin1String("UrlResponse") #define SSOUI_KEY_CAPTCHAURL QLatin1String("CaptchaUrl") #define SSOUI_KEY_CAPTCHAIMG QLatin1String("CaptchaImage") //QByteArray !!! #define SSOUI_KEY_CAPTCHARESP QLatin1String("CaptchaResponse") #define SSOUI_KEY_REQUESTID QLatin1String("requestId") //id of request, used for cancellation #define SSOUI_KEY_REFRESH QLatin1String("refreshRequired") //id of request, used for cancellation #define SSOUI_KEY_WATCHDOG QLatin1String("watchdog") // automatic behavior of dialog #define SSOUI_KEY_STORED_IDENTITY QLatin1String("StoredIdentity") /* flag whether the credentials are stored or not */ #define SSOUI_KEY_IDENTITY QLatin1String("Identity") // Credentials ID #define SSOUI_KEY_FORGOTPASSWORD QLatin1String("ForgotPassword") #define SSOUI_KEY_FORGOTPASSWORDURL QLatin1String("ForgotPasswordUrl") #define SSOUI_KEY_REPLYCOOKIES QLatin1String("ReplyCookies") #define SSOUI_KEY_WINDOWID QLatin1String("WindowId") #define SSOUI_KEY_CONFIRM QLatin1String("Confirm") #define SSOUI_KEY_ICON QLatin1String("Icon") #define SSOUI_KEY_TITLE QLatin1String("Title") #define SSOUI_KEY_CONFIRMCOUNT QLatin1String("ConfirmCount") /* Embed the signon-ui in the window given by SSOUI_KEY_WINDOWID */ #define SSOUI_KEY_EMBEDDED QLatin1String("Embedded") /* Contains the original request parameters, as sent from the application */ #define SSOUI_KEY_CLIENT_DATA QLatin1String("ClientData") /* Method and mechanism; these could be used, along with the IDENTITY * and CLIENT_DATA keys above, to replay the authentication. */ #define SSOUI_KEY_METHOD QLatin1String("Method") #define SSOUI_KEY_MECHANISM QLatin1String("Mechanism") /* Process ID of the client application */ #define SSOUI_KEY_PID QLatin1String("Pid") /* Application ID (security context) of the client application */ #define SSOUI_KEY_APP_ID QLatin1String("AppId") #define SSOUI_KEY_SLOT_ACCEPT "accept" #define SSOUI_KEY_SLOT_REJECT "reject" #define SSOUI_KEY_SLOT_REFRESH "refresh" #define SSOUI_KEY_STORAGE_KEYS_UNAVAILABLE \ QLatin1String("SecStorageKeysUnavailable") #define SSOUI_KEY_UNABLE_TO_QUERY_STORAGE_KEYS \ QLatin1String("SecStorageUnableQueryKeys") #endif /* UISESSIONDATA_PRIV_H */ signond-nicolasfella/lib/plugins/SignOn/authpluginif.h0000664000175000017500000001770414615454547023367 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef AUTHPLUGINIF_H #define AUTHPLUGINIF_H #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QString; class QByteArray; class QVariant; QT_END_NAMESPACE /*! * Predefined states to be used for progress reporting. */ enum AuthPluginState { PLUGIN_STATE_NONE = 0, /**< State unknown. */ PLUGIN_STATE_RESOLVING, /**< Resolving remote server host name. */ PLUGIN_STATE_CONNECTING, /**< Connecting to remote server. */ PLUGIN_STATE_SENDING, /**< Sending data to remote server. */ PLUGIN_STATE_WAITING, /**< Waiting for reply from remote server. */ PLUGIN_STATE_PENDING, /**< Waiting for response from user. */ PLUGIN_STATE_REFRESHING, /**< Refreshing ui request. */ PLUGIN_STATE_CANCELING, /**< Canceling current process. */ PLUGIN_STATE_HOLDING, /**< Holding long non-expired token. Process should be kept alive. */ PLUGIN_STATE_DONE /**< Process is finished. Process can be terminated. */ }; /*! * Macro to create declarations of * SSO authentication plugin. * */ #define SIGNON_PLUGIN_INSTANCE(pluginclass) \ { \ static AuthPluginInterface *_instance = 0; \ if (!_instance) \ _instance = static_cast(new pluginclass()); \ return _instance; \ } #define SIGNON_DECL_AUTH_PLUGIN(pluginclass) \ extern "C" AuthPluginInterface *auth_plugin_instance() \ SIGNON_PLUGIN_INSTANCE(pluginclass) /*! * @class AuthPluginInterface. * Interface definition for authentication plugins */ class AuthPluginInterface : public QObject { Q_OBJECT public: AuthPluginInterface(QObject *parent = 0) : QObject(parent) { qRegisterMetaType("SignOn::Error"); } /*! * Destructor */ virtual ~AuthPluginInterface() {} /*! * Gets the type of the plugin * * @return Plugin type */ virtual QString type() const = 0; /*! * Gets the list of supported mechanisms. * * @return List of mechanisms */ virtual QStringList mechanisms() const = 0; /*! * Requests to cancel the process. * Process is terminated after this call. * Reimplement this in order to execute specific instructions before * the effective cancel occurres. */ virtual void cancel() {} /*! * Requests to abort the process. * Process is terminated after this call. * Reimplement this in order to execute specific instructions before * process is killed. */ virtual void abort() {} /*! * Process authentication. * Authentication can be logging to a server, obtain token(s) from a server, * calculate response using given challenge, etc. * Given session data is used to do authentication and return response. * Signal result() is emitted when authentication is completed, * or signal error() if authentication failed. * @see result * @see error * * @param inData Input data for authentication * @param mechanism Mechanism to use to do authentication */ virtual void process(const SignOn::SessionData &inData, const QString &mechanism = QString()) = 0; Q_SIGNALS: /*! * Emitted when authentication process has been completed for given data * and there are no errors. * * @param data Resulting SessionData, need to be returned to client */ void result(const SignOn::SessionData &data); /*! * Emitted when authentication process want to store session data parameters * for later use. Stored parameters are added into SessionData in following process calls. * This is useful when authentication is using permanent tokens. * * @note This is shared within same identity using same method only. * @note There can be storage size limitation for data that can be stored. * * @param data Resulting SessionData, need to be returned to client */ void store(const SignOn::SessionData &data); /*! * Emitted when authentication process has been completed for given data * and resulting an error. * * @param err The error object * @param errorMessage Resulting error message */ void error(const SignOn::Error &err); /*! * Emitted when authentication process need to interact with user. * Basic use cases are: query password, verify captcha, show url. * Can also be used to get username/password for proxy authentication etc. * Slot userActionFinished() is called when interaction is completed. * * @see userActionFinished * @see SignOn::UiSessionData * @note slot userActionFinished() should be reimplemented to get result. * * @param data Ui session data to be filled within user interaction */ void userActionRequired(const SignOn::UiSessionData &data); /*! * Emitted when authentication process has completed refresh request. * Plugin must emit signal refreshed() to response to refresh() call. * @see refreshed * * @param data Refreshed ui session data */ void refreshed(const SignOn::UiSessionData &data); /*! * Emitted to report status of authentication process to signond for * informing client application. * * @param state Plugin process state @see AuthPluginState * @param message Optional message for client application */ void statusChanged(const AuthPluginState state, const QString &message = QString()); public Q_SLOTS: /*! * User interaction completed. * Signond uses this slot to notice the end of ui session. * This is a response to userActionRequired() signal. * This must be reimplemented to get the response from the user interaction. * @see UiSessionData * @see userActionRequired * * @param data User completed ui session data */ virtual void userActionFinished(const SignOn::UiSessionData &data) { Q_UNUSED(data); } /*! * Refreshes given session. * Signond uses this slot to refresh data in given ui session. * Mostly used to refresh a captcha images during the user interaction. * Signal refreshed() or error() must be emitted when refresh is completed. * This must be reimplemented to refresh the captcha image. * @see UiSessionData * @see refreshed * @note emitting signal userActionRequired() is not allowed to use before ui session is finished. * * @param data Ui session data to be refreshed */ virtual void refresh(const SignOn::UiSessionData &data) { emit refreshed(data); } }; QT_BEGIN_NAMESPACE Q_DECLARE_INTERFACE(AuthPluginInterface, "com.nokia.SingleSignOn.PluginInterface/1.3") QT_END_NAMESPACE #endif // AUTHPLUGINIF_H signond-nicolasfella/lib/plugins/doc/0000775000175000017500000000000014615454535020053 5ustar coucoufcoucoufsignond-nicolasfella/lib/plugins/doc/doc.pri0000664000175000017500000000527414615454535021344 0ustar coucoufcoucouf#----------------------------------------------------------------------------- # doc.pri #----------------------------------------------------------------------------- # list of documentation folders to install DOC_FOLDERS = doc/html \ doc/qch # files and folders listed in the installation target's .files section # must exist _before_ qmake generates the Makefile...so, make sure our # documentation target folders exist in the current build folder for( folder, DOC_FOLDERS ) { system( mkdir -p $$(PWD)/$${folder} ) } #----------------------------------------------------------------------------- # extra build targets for generating and cleaning documentation #----------------------------------------------------------------------------- DOC_INPUT += $${_PRO_FILE_PWD_} DOC_INPUT += doc/src # target for generating documentation doctarget.target = docs doctarget.commands = OUTPUT_DIRECTORY=doc \ PROJECT_NAME=\"$${PROJECT_NAME}\" \ PROJECT_NUMBER=\"$${PROJECT_VERSION}\" \ STRIP_FROM_PATH=\"$${_PRO_FILE_PWD_}\" \ INPUT=\"$${DOC_INPUT}\" \ QHP_NAMESPACE=\"com.nokia.example.$${TARGET}\" \ QHP_VIRTUAL_FOLDER=\"$${TARGET}\" \ TAGFILES=\"$$system(pwd)/qt.tags\" \ TAGFILE=\"doc/$${TARGET}.tags\" \ doxygen $$system(pwd)/doxy.conf doctarget.depends = FORCE QMAKE_EXTRA_TARGETS += doctarget # target for cleaning generated documentation doccleantarget.target = cleandocs for( folder, DOC_FOLDERS ) { doccleantarget.commands += rm -r -f $${folder}; } doccleantarget.commands += rm -r -f doc/accounts.tags; doccleantarget.depends = FORCE QMAKE_EXTRA_TARGETS += doccleantarget #----------------------------------------------------------------------------- # installation setup # NOTE: remember to set headers.files before this include to have the headers # properly setup. #----------------------------------------------------------------------------- include( ../../../common-project-config.pri ) include( $${TOP_SRC_DIR}/common-installs-config.pri ) #----------------------------------------------------------------------------- # Installation target setup for documentation #----------------------------------------------------------------------------- documentation.path = $${INSTALL_PREFIX}/share/doc/$${TARGET} for( folder, DOC_FOLDERS ) { documentation.files += $${folder} } # make sure docs are generated before trying to install anything documentation.depends = docs INSTALLS += documentation message("====") message("==== INSTALLS += documentation") # End of File signond-nicolasfella/lib/plugins/doc/doxy.conf0000664000175000017500000017336414615454535021723 0ustar coucoufcoucouf# Doxyfile 1.5.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = $(PROJECT_NAME) # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = $(PROJECT_NUMBER) # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = $(OUTPUT_DIRECTORY) # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, # Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = $(STRIP_FROM_PATH) # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = YES # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = YES # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = $(INPUT) # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.cpp \ *.h \ *.dox # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */.moc/* \ */.obj/* \ */.git/* \ *impl.cpp \ *impl.h \ moc_* \ */tests/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = YES # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = ../qch/signon.qch # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = $(QHP_NAMESPACE) # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = $(QHP_VIRTUAL_FOLDER) # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = qhelpgenerator # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to FRAME, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = ALL # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = $(TAGFILES) # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = $(TAGFILE) # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO # End of File signond-nicolasfella/lib/plugins/doc/src/0000775000175000017500000000000014615454535020642 5ustar coucoufcoucoufsignond-nicolasfella/lib/plugins/doc/src/mainpage.dox0000664000175000017500000000166014615454535023142 0ustar coucoufcoucouf/*! \mainpage SignOn plugin development @section intro Introduction This library contains the interface definition and a few classes that should be used when implementing an authentication plugin for the Single Sign On framework. @section usage Usage Since it currently consists of a few header files and of a single moc-generated .cpp file, the library is built statically. The library ships with a pkg-config file (@a signon-plugins.pc). @section classlist List of classes in libsignon-qt Here are the main classes in the libraries. You can also see the complete list of classes. All classes but the AuthPluginInterface reside in the SignOn namespace.
AuthPluginInterfaceInterface to be implemented by all authentication plugins.
SignOn::UiSessionDataDictionary of data to be exchanged between the plugin and the SignOn UI.
*/ signond-nicolasfella/lib/plugins/plugins.pro0000664000175000017500000000020514615454535021506 0ustar coucoufcoucoufTEMPLATE = subdirs CONFIG += ordered SUBDIRS = signon-plugins.pro signon-plugins-common TARGET=signon-plugins include(doc/doc.pri) signond-nicolasfella/lib/plugins/signon-plugins-common/0000775000175000017500000000000014615454547023553 5ustar coucoufcoucoufsignond-nicolasfella/lib/plugins/signon-plugins-common/SignOn/0000775000175000017500000000000014615454547024750 5ustar coucoufcoucoufsignond-nicolasfella/lib/plugins/signon-plugins-common/SignOn/blobiohandler.h0000664000175000017500000000375714615454535027736 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef BLOBIOHANDLER_H #define BLOBIOHANDLER_H #include #include #include #include namespace SignOn { class BlobIOHandler: public QObject { Q_OBJECT public: BlobIOHandler(QIODevice *inputChannel, QIODevice *outputChannel, QObject *parent = 0); //sync call bool sendData(const QVariantMap &map); //async call void receiveData(int expectedDataSize); void setReadChannelSocketNotifier(QSocketNotifier *notifier); bool isReading() const { return m_isReading; } public Q_SLOTS: void readBlob(); Q_SIGNALS: void dataReceived(const QVariantMap &map); void error(); private: void setReadNotificationEnabled(bool enable); QByteArray variantMapToByteArray(const QVariantMap &map); QVariantMap byteArrayToVariantMap(const QByteArray &array); QVector pageByteArray(const QByteArray &array); public: QIODevice *m_readChannel; QIODevice *m_writeChannel; QByteArray m_blobBuffer; QSocketNotifier *m_readNotifier; int m_blobSize; bool m_isReading; }; } #endif //BLOBIOHANDLER_H signond-nicolasfella/lib/plugins/signon-plugins-common/SignOn/ipc.h0000664000175000017500000000271314615454535025674 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNON_PLUGINS_COMMON_IPC_H #define SIGNON_PLUGINS_COMMON_IPC_H enum PluginOperation { PLUGIN_OP_TYPE = 1, PLUGIN_OP_MECHANISMS, PLUGIN_OP_PROCESS, PLUGIN_OP_PROCESS_UI, PLUGIN_OP_REFRESH, PLUGIN_OP_CANCEL, PLUGIN_OP_STOP, PLUGIN_OP_LAST }; enum PluginResponse { PLUGIN_RESPONSE_RESULT = 1, PLUGIN_RESPONSE_STORE, PLUGIN_RESPONSE_ERROR, PLUGIN_RESPONSE_SIGNAL, PLUGIN_RESPONSE_UI, PLUGIN_RESPONSE_REFRESHED, PLUGIN_RESPONSE_LAST }; #endif // SIGNON_PLUGINS_COMMON_IPC_H signond-nicolasfella/lib/plugins/signon-plugins-common/SignOn/blobiohandler.cpp0000664000175000017500000001604114615454547030262 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "blobiohandler.h" #include #include #include #include #include "SignOn/signonplugincommon.h" #define SIGNON_IPC_BUFFER_PAGE_SIZE 16384 using namespace SignOn; BlobIOHandler::BlobIOHandler(QIODevice *readChannel, QIODevice *writeChannel, QObject *parent): QObject(parent), m_readChannel(readChannel), m_writeChannel(writeChannel), m_readNotifier(0), m_blobSize(-1), m_isReading(false) { } void BlobIOHandler::setReadChannelSocketNotifier(QSocketNotifier *notifier) { if (notifier == 0) return; m_readNotifier = notifier; } bool BlobIOHandler::sendData(const QVariantMap &map) { if (m_writeChannel == 0) { TRACE() << "NULL write channel."; return false; } QDataStream stream(m_writeChannel); QByteArray ba = variantMapToByteArray(map); // in Qt6 QByteArray::size() is 64 bit, but the receiving side expects int stream << static_cast(ba.size()); QVector pages = pageByteArray(ba); for (int i = 0; i < pages.count(); ++i) stream << pages[i]; return true; } void BlobIOHandler::setReadNotificationEnabled(bool enabled) { m_isReading = enabled; if (enabled) { if (m_readNotifier != 0) { connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readBlob())); } else { connect(m_readChannel, SIGNAL(readyRead()), this, SLOT(readBlob())); } } else { if (m_readNotifier != 0) { disconnect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readBlob())); } else { disconnect(m_readChannel, SIGNAL(readyRead()), this, SLOT(readBlob())); } } } void BlobIOHandler::receiveData(int expectedDataSize) { m_blobBuffer.clear(); m_blobSize = expectedDataSize; //Enable read notification only if more than 1 BLOB page is to be received //This does not allow duplicate read attempts if only 1 page is available if (m_blobSize > SIGNON_IPC_BUFFER_PAGE_SIZE) setReadNotificationEnabled(true); readBlob(); } void BlobIOHandler::readBlob() { QDataStream in(m_readChannel); QByteArray fractionBa; in >> fractionBa; m_blobBuffer.append(fractionBa); //Avoid infinite loops if the other party behaves badly if ((fractionBa.size() == 0) && (m_blobBuffer.size() < m_blobSize)) { setReadNotificationEnabled(false); emit error(); return; } if (m_blobBuffer.size() == m_blobSize) { QVariantMap sessionDataMap; sessionDataMap = byteArrayToVariantMap(m_blobBuffer); if (m_blobSize > SIGNON_IPC_BUFFER_PAGE_SIZE) setReadNotificationEnabled(false); emit dataReceived(sessionDataMap); } } QVariantMap expandDBusArgumentValue(const QVariant &value, bool *success) { // first, convert the QDBusArgument to a map QDBusArgument dbusValue = value.value(); QVariantMap converted; if (dbusValue.currentType() == QDBusArgument::MapType && // We only care about a{sv} dbusValue.currentSignature() == "a{sv}") { converted = qdbus_cast(dbusValue); } else { *success = false; return QVariantMap(); } // Then, check each value of the converted map // and if any QDBusArgument is a value, convert that. QVariantMap returnValue; QVariantMap::const_iterator i; for (i = converted.constBegin(); i != converted.constEnd(); ++i) { if (qstrcmp(i.value().typeName(), "QDBusArgument") == 0) { QVariantMap convertedValue = expandDBusArgumentValue(i.value(), success); if (*success == false) { //bail out to prevent error in serialization return QVariantMap(); } returnValue.insert(i.key(), convertedValue); } else { returnValue.insert(i.key(), i.value()); } } return returnValue; } static QVariantMap filterOutComplexTypes(const QVariantMap &map) { QVariantMap filteredMap; QVariantMap::const_iterator i; for (i = map.constBegin(); i != map.constEnd(); i++) { if (qstrcmp(i.value().typeName(), "QDBusArgument") == 0) { bool success = true; QVariantMap convertedMap = expandDBusArgumentValue(i.value(), &success); if (success == false) { /* QDBusArgument are complex types; there is no QDataStream * serialization for them, so keeping them in the map would * make the serialization fail for the whole map, if we are * unable to convert to a QVariantMap. * Therefore, skip them. */ BLAME() << "Found non-map QDBusArgument in data; skipping."; continue; } filteredMap.insert(i.key(), convertedMap); } else { filteredMap.insert(i.key(), i.value()); } } return filteredMap; } QByteArray BlobIOHandler::variantMapToByteArray(const QVariantMap &map) { QBuffer buffer; if (!buffer.open(QIODevice::WriteOnly)) BLAME() << "Buffer opening failed."; QDataStream stream(&buffer); stream << filterOutComplexTypes(map); buffer.close(); return buffer.data(); } QVariantMap BlobIOHandler::byteArrayToVariantMap(const QByteArray &array) { QByteArray nonConst = array; QBuffer buffer(&nonConst); if (!buffer.open(QIODevice::ReadOnly)) BLAME() << "Buffer opening failed."; buffer.reset(); QDataStream stream(&buffer); QVariantMap map; stream >> map; buffer.close(); return map; } QVector BlobIOHandler::pageByteArray(const QByteArray &array) { QVector dataPages; QByteArray ba = array; QBuffer pagingBuffer(&ba); if (!pagingBuffer.open(QIODevice::ReadOnly)) BLAME() << "Error while paging BLOB. Buffer opening failed."; while (!pagingBuffer.atEnd()) { QByteArray page = pagingBuffer.read(SIGNON_IPC_BUFFER_PAGE_SIZE); dataPages.append(page); } pagingBuffer.close(); return dataPages; } signond-nicolasfella/lib/plugins/signon-plugins-common/signon-plugins-common.pro0000664000175000017500000000117214615454535030535 0ustar coucoufcoucoufTEMPLATE = lib TARGET = signon-plugins-common include( ../../../common-project-config.pri ) include($${TOP_SRC_DIR}/common-installs-config.pri) include($${TOP_SRC_DIR}/common-vars.pri) CONFIG += qt QT += dbus INCLUDEPATH += ../ \ $${TOP_SRC_DIR}/lib DEFINES += SIGNON_PLUGIN_TRACE SOURCES += \ SignOn/blobiohandler.cpp HEADERS += \ SignOn/blobiohandler.h \ SignOn/ipc.h headers.files = \ SignOn/blobiohandler.h headers.path = $${INSTALL_PREFIX}/include/signon-plugins/SignOn INSTALLS += headers pkgconfig.files = signon-plugins-common.pc include($${TOP_SRC_DIR}/common-pkgconfig.pri) INSTALLS += pkgconfig signond-nicolasfella/lib/plugins/signon-plugins-common/signon-plugins-common.pc.in0000664000175000017500000000056514615454547030754 0ustar coucoufcoucoufprefix=$$INSTALL_PREFIX exec_prefix=${prefix} libdir=$$INSTALL_LIBDIR includedir=${prefix}/include plugin_includedir=${includedir}/signon-plugins/SignOn Name: signon-plugins-common Description: SignonPluginsCommon Version: $$PROJECT_VERSION Libs.private: -L/usr/lib -lQt$${QT_MAJOR_VERSION}Core Cflags: -I${includedir}/signon-plugins -I${includedir}/signon-plugins/SignOn signond-nicolasfella/lib/plugins/signon-plugins.pro0000664000175000017500000000126014615454535023003 0ustar coucoufcoucoufTEMPLATE = lib TARGET = signon-plugins include( ../../common-project-config.pri ) include($${TOP_SRC_DIR}/common-installs-config.pri) include($${TOP_SRC_DIR}/common-vars.pri) INCLUDEPATH += .. HEADERS = \ SignOn/authpluginif.h \ SignOn/uisessiondata.h \ SignOn/uisessiondata_priv.h headers.files = \ SignOn/AuthPluginInterface \ SignOn/authpluginif.h \ SignOn/signonplugincommon.h \ SignOn/UiSessionData \ SignOn/uisessiondata.h \ SignOn/uisessiondata_priv.h headers.path = $${INSTALL_PREFIX}/include/signon-plugins/SignOn INSTALLS += headers pkgconfig.files = signon-plugins.pc include($${TOP_SRC_DIR}/common-pkgconfig.pri) INSTALLS += pkgconfig signond-nicolasfella/lib/plugins/signon-plugins.pc.in0000664000175000017500000000066714615454547023227 0ustar coucoufcoucoufprefix=$$INSTALL_PREFIX exec_prefix=${prefix} libdir=$$INSTALL_LIBDIR includedir=${prefix}/include plugin_includedir=${includedir}/signon-plugins/SignOn plugindir=$$SIGNOND_PLUGINS_DIR Name: signon-plugins Description: SignonPlugins Version: $$PROJECT_VERSION Requires: $${LIBSIGNON} Libs.private: -L/usr/lib -lQt$${QT_MAJOR_VERSION}Core Cflags: -I${includedir}/signon-plugins -I${includedir}/signon-plugins/SignOn Libs: -lsignon-plugins signond-nicolasfella/lib/signond/0000775000175000017500000000000014615454535017266 5ustar coucoufcoucoufsignond-nicolasfella/lib/signond/SignOn/0000775000175000017500000000000014615454547020466 5ustar coucoufcoucoufsignond-nicolasfella/lib/signond/SignOn/AbstractAccessControlManager0000664000175000017500000000006514615454535026130 0ustar coucoufcoucouf#include signond-nicolasfella/lib/signond/SignOn/AbstractCryptoManager0000664000175000017500000000005514615454535024645 0ustar coucoufcoucouf#include signond-nicolasfella/lib/signond/SignOn/AbstractKeyAuthorizer0000664000175000017500000000005514615454535024677 0ustar coucoufcoucouf#include signond-nicolasfella/lib/signond/SignOn/AbstractKeyManager0000664000175000017500000000005214615454535024112 0ustar coucoufcoucouf#include signond-nicolasfella/lib/signond/SignOn/AbstractSecretsStorage0000664000175000017500000000005514615454535025027 0ustar coucoufcoucouf#include signond-nicolasfella/lib/signond/SignOn/Debug0000664000175000017500000000003314615454535021430 0ustar coucoufcoucouf#include signond-nicolasfella/lib/signond/SignOn/ExtensionInterface0000664000175000017500000000005114615454535024177 0ustar coucoufcoucouf#include signond-nicolasfella/lib/signond/SignOn/KeyHandler0000664000175000017500000000004114615454535022427 0ustar coucoufcoucouf#include signond-nicolasfella/lib/signond/SignOn/SignOn.pro0000664000175000017500000000006714615454535022405 0ustar coucoufcoucoufTEMPLATE = subdirs SUBDIRS = \ SignOnExtension.pro signond-nicolasfella/lib/signond/SignOn/SignOnExtension.pro0000664000175000017500000000321214615454535024275 0ustar coucoufcoucoufinclude( ../../../common-project-config.pri ) include( $${TOP_SRC_DIR}/common-vars.pri ) TEMPLATE = lib TARGET = signon-extension HEADERS = \ abstract-access-control-manager.h \ abstract-crypto-manager.h \ abstract-key-authorizer.h \ abstract-key-manager.h \ abstract-secrets-storage.h \ debug.h \ export.h \ extension-interface.h \ key-handler.h \ misc.h INCLUDEPATH += \ .. SOURCES += \ abstract-access-control-manager.cpp \ abstract-crypto-manager.cpp \ abstract-key-authorizer.cpp \ abstract-key-manager.cpp \ abstract-secrets-storage.cpp \ debug.cpp \ extension-interface.cpp \ key-handler.cpp \ misc.cpp QT += core \ dbus QMAKE_CXXFLAGS += \ -fvisibility=hidden # Error on undefined symbols QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII DEFINES += \ BUILDING_SIGNON \ SIGNON_ENABLE_UNSTABLE_APIS \ SIGNON_TRACE include( $${TOP_SRC_DIR}/common-installs-config.pri ) headers.files = \ AbstractAccessControlManager \ abstract-access-control-manager.h \ AbstractCryptoManager \ abstract-crypto-manager.h \ AbstractKeyAuthorizer \ abstract-key-authorizer.h \ AbstractKeyManager \ abstract-key-manager.h \ AbstractSecretsStorage \ abstract-secrets-storage.h \ Debug \ debug.h \ export.h \ ExtensionInterface \ extension-interface.h \ KeyHandler \ key-handler.h headers.path = $${INSTALL_PREFIX}/include/$${TARGET}/SignOn INSTALLS += headers pkgconfig.files = SignOnExtension.pc include($${TOP_SRC_DIR}/common-pkgconfig.pri) INSTALLS += pkgconfig signond-nicolasfella/lib/signond/SignOn/abstract-access-control-manager.cpp0000664000175000017500000001073314615454535027323 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Elena Reshetova * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "abstract-access-control-manager.h" #include #include #include using namespace SignOn; namespace SignOn { class AccessRequestData: public QSharedData { public: AccessRequestData(); AccessRequestData(const AccessRequestData &other); ~AccessRequestData() {}; QDBusConnection m_connection; QDBusMessage m_message; quint32 m_identity; }; } // namespace AccessRequestData::AccessRequestData(): m_connection(QLatin1String("invalid")), m_message(), m_identity(0) { } AccessRequestData::AccessRequestData(const AccessRequestData &other): QSharedData(other), m_connection(other.m_connection), m_message(other.m_message), m_identity(other.m_identity) { } AccessRequest::AccessRequest(): d(new AccessRequestData) { } AccessRequest::AccessRequest(const AccessRequest &other): d(other.d) { } AccessRequest::~AccessRequest() { } void AccessRequest::setPeer(const QDBusConnection &connection, const QDBusMessage &message) { d->m_connection = connection; d->m_message = message; } const QDBusConnection &AccessRequest::peerConnection() const { return d->m_connection; } const QDBusMessage &AccessRequest::peerMessage() const { return d->m_message; } void AccessRequest::setIdentity(quint32 id) { d->m_identity = id; } quint32 AccessRequest::identity() const { return d->m_identity; } namespace SignOn { class AccessReplyPrivate { public: inline AccessReplyPrivate(const AccessRequest &request); private: friend class AccessReply; AccessRequest m_request; bool m_isAccepted; }; } // namespace AccessReplyPrivate::AccessReplyPrivate(const AccessRequest &request): m_request(request), m_isAccepted(false) { } AccessReply::AccessReply(const AccessRequest &request, QObject *parent): QObject(parent), d_ptr(new AccessReplyPrivate(request)) { } AccessReply::~AccessReply() { delete d_ptr; } const AccessRequest &AccessReply::request() const { Q_D(const AccessReply); return d->m_request; } bool AccessReply::isAccepted() const { Q_D(const AccessReply); return d->m_isAccepted; } void AccessReply::accept() { Q_D(AccessReply); d->m_isAccepted = true; Q_EMIT finished(); } void AccessReply::decline() { Q_D(AccessReply); d->m_isAccepted = false; Q_EMIT finished(); } AbstractAccessControlManager::AbstractAccessControlManager(QObject *parent): QObject(parent) { } AbstractAccessControlManager::~AbstractAccessControlManager() { } QString AbstractAccessControlManager::keychainWidgetAppId() { return QString(); } bool AbstractAccessControlManager::isPeerAllowedToAccess( const QDBusConnection &peerConnection, const QDBusMessage &peerMessage, const QString &securityContext) { Q_UNUSED(peerConnection); Q_UNUSED(peerMessage); Q_UNUSED(securityContext); return true; } QString AbstractAccessControlManager::appIdOfPeer( const QDBusConnection &peerConnection, const QDBusMessage &peerMessage) { Q_UNUSED(peerConnection); Q_UNUSED(peerMessage); return QString(); } AccessReply * AbstractAccessControlManager::handleRequest(const AccessRequest &request) { /* The default implementation creates a reply and accepts it */ AccessReply *reply = new AccessReply(request, this); QMetaObject::invokeMethod(reply, "accept", Qt::QueuedConnection); return reply; } signond-nicolasfella/lib/signond/SignOn/abstract-access-control-manager.h0000664000175000017500000001150514615454535026766 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Elena Reshetova * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @file abstract-access-control-manager.h * Definition of the AbstractAccessControlManager object. * @ingroup Accounts_and_SSO_Framework */ #ifndef SIGNON_ABSTRACT_ACCESS_CONTROL_MANAGER_H #define SIGNON_ABSTRACT_ACCESS_CONTROL_MANAGER_H #include #include #include class QDBusConnection; class QDBusMessage; namespace SignOn { class AbstractAccessControlManager; class AccessRequestData; class SIGNON_EXPORT AccessRequest { public: explicit AccessRequest(); AccessRequest(const AccessRequest &other); ~AccessRequest(); /*! * Identifies the client requesting the access. * @param peerConnection the connection over which the message was sent. * @param peerMessage, the request message sent over DBUS by the process. */ void setPeer(const QDBusConnection &connection, const QDBusMessage &message); const QDBusConnection &peerConnection() const; const QDBusMessage &peerMessage() const; /*! * Specifies the SignOn::Identity resource being accessed. */ void setIdentity(quint32 id); quint32 identity() const; private: QSharedDataPointer d; }; class AccessReplyPrivate; class SIGNON_EXPORT AccessReply: public QObject { Q_OBJECT public: ~AccessReply(); const AccessRequest &request() const; bool isAccepted() const; Q_SIGNALS: void finished(); protected: explicit AccessReply(const AccessRequest &request, QObject *parent = 0); protected Q_SLOTS: void accept(); void decline(); private: friend class AbstractAccessControlManager; AccessReplyPrivate *d_ptr; Q_DECLARE_PRIVATE(AccessReply) }; /*! * @class AbstractAccessControlManager * Helps filtering incoming Singnon Daemon requests, * based on security priviledges of the client processes. * @ingroup Accounts_and_SSO_Framework */ class SIGNON_EXPORT AbstractAccessControlManager: public QObject { Q_OBJECT public: /*! * Constructs a AbstractAccessControlManager object with the given parent. * @param parent */ explicit AbstractAccessControlManager(QObject *parent = 0); /*! * Destructor. */ virtual ~AbstractAccessControlManager(); /*! * Checks if a client process is allowed to access objects with a certain * security context. * The access type to be checked depends on the concrete implementation of * this function. * @param peerConnection the connection over which the message was sent. * @param peerMessage, the request message sent over DBUS by the process. * @param securityContext, the securityContext to be checked against. * @returns true, if the peer is allowed, false otherwise. */ virtual bool isPeerAllowedToAccess(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage, const QString &securityContext); /*! * Looks up for the application identifier of a specific client process. * @param peerConnection the connection over which the message was sent. * @param peerMessage, the request message sent over DBUS by the process. * @returns the application identifier of the process, or an empty string * if none found. */ virtual QString appIdOfPeer(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage); /*! * @returns the application identifier of the keychain widget */ virtual QString keychainWidgetAppId(); /*! * Asynchronously handle an access request from a client. * @param request, the AccessRequest describing the requested access. * @returns an AccessReply object which can be used to obtain the * asynchronous reply. */ virtual AccessReply *handleRequest(const AccessRequest &request); }; } // namespace #endif // SIGNON_ABSTRACT_ACCESS_CONTROL_MANAGER_H signond-nicolasfella/lib/signond/SignOn/abstract-crypto-manager.cpp0000664000175000017500000000774414615454535025734 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "abstract-crypto-manager.h" #include "debug.h" using namespace SignOn; namespace SignOn { class AbstractCryptoManagerPrivate { Q_DECLARE_PUBLIC(AbstractCryptoManager) public: AbstractCryptoManagerPrivate(AbstractCryptoManager *cryptoManager); ~AbstractCryptoManagerPrivate() {}; private: mutable AbstractCryptoManager *q_ptr; Key m_encryptionKey; bool m_fileSystemIsSetup; bool m_fileSystemIsMounted; }; }; AbstractCryptoManagerPrivate::AbstractCryptoManagerPrivate( AbstractCryptoManager *cryptoManager): q_ptr(cryptoManager), m_fileSystemIsSetup(false), m_fileSystemIsMounted(false) { } AbstractCryptoManager::AbstractCryptoManager(QObject *parent): QObject(parent), d_ptr(new AbstractCryptoManagerPrivate(this)) { } AbstractCryptoManager::~AbstractCryptoManager() { delete d_ptr; } void AbstractCryptoManager::setEncryptionKey(const SignOn::Key &key) { if (fileSystemIsMounted()) { BLAME() << "File system already mounted"; return; } d_ptr->m_encryptionKey = key; } SignOn::Key AbstractCryptoManager::encryptionKey() const { return d_ptr->m_encryptionKey; } bool AbstractCryptoManager::initialize(const QVariantMap &configuration) { Q_UNUSED(configuration); return true; } bool AbstractCryptoManager::setupFileSystem() { setFileSystemSetup(true); return true; } bool AbstractCryptoManager::deleteFileSystem() { setFileSystemSetup(false); return true; } bool AbstractCryptoManager::fileSystemIsSetup() const { return d_ptr->m_fileSystemIsSetup; } bool AbstractCryptoManager::mountFileSystem() { setFileSystemMounted(true); return true; } bool AbstractCryptoManager::unmountFileSystem() { setFileSystemMounted(false); return true; } bool AbstractCryptoManager::fileSystemIsMounted() const { return d_ptr->m_fileSystemIsMounted; } QString AbstractCryptoManager::fileSystemMountPath() const { return QString(); } QStringList AbstractCryptoManager::backupFiles() const { return QStringList(); } bool AbstractCryptoManager::encryptionKeyInUse(const SignOn::Key &key) { Q_UNUSED(key); return true; } bool AbstractCryptoManager::addEncryptionKey(const SignOn::Key &key, const SignOn::Key &existingKey) { Q_UNUSED(key); Q_UNUSED(existingKey); return true; } bool AbstractCryptoManager::removeEncryptionKey(const SignOn::Key &key, const SignOn::Key &remainingKey) { Q_UNUSED(key); Q_UNUSED(remainingKey); return true; } void AbstractCryptoManager::setFileSystemMounted(bool isMounted) { Q_D(AbstractCryptoManager); if (isMounted != d->m_fileSystemIsMounted) { if (d->m_fileSystemIsMounted) { Q_EMIT fileSystemUnmounting(); } d->m_fileSystemIsMounted = isMounted; if (isMounted) { Q_EMIT fileSystemMounted(); } } } void AbstractCryptoManager::setFileSystemSetup(bool isSetup) { Q_D(AbstractCryptoManager); if (isSetup != d->m_fileSystemIsSetup) { d->m_fileSystemIsSetup = isSetup; } } signond-nicolasfella/lib/signond/SignOn/abstract-crypto-manager.h0000664000175000017500000001230514615454535025366 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @file cryptomanager.h * Definition of the AbstractCryptoManager object. * @ingroup Accounts_and_SSO_Framework */ #ifndef SIGNON_ABSTRACT_CRYPTO_MANAGER_H #define SIGNON_ABSTRACT_CRYPTO_MANAGER_H #include "SignOn/abstract-key-manager.h" #include #include #include namespace SignOn { class AbstractCryptoManagerPrivate; /*! * @class AbstractCryptoManager * Manages the credentials storage file system encryption. The API is modeled * after a LUKS-based implementation. * @ingroup Accounts_and_SSO_Framework */ class SIGNON_EXPORT AbstractCryptoManager: public QObject { Q_OBJECT public: /*! * Constructs a AbstractCryptoManager object with the given parent. * @param parent */ explicit AbstractCryptoManager(QObject *parent = 0); /*! * Destructor. */ ~AbstractCryptoManager(); /*! * Sets the encryption key. * @param key the encrypted file system key. */ void setEncryptionKey(const SignOn::Key &key); /*! * @return The in use encryption key. */ SignOn::Key encryptionKey() const; /*! * Initializes the object with the given configuration. * @param configuration A dictionary of configuration options, dependent on * the specific crypto-manager implementation. * @returns true if the configuration is valid. */ virtual bool initialize(const QVariantMap &configuration); /*! * Sets up an encrypted file system. This method is to be called only at * the file system creation/foramtting. * Use mountFileSystem() on subsequent uses. This method handles also the * mounting so when using it, a call to mountFileSystem() is not necessary. * * @returns true if successful, false otherwise. * @warning this method might format the credentials file system, use * carefully. */ virtual bool setupFileSystem(); /*! * Deletes the encrypted file system. * @returns true if successful, false otherwise. * @warning use this carefully, this will lead to data loss. */ virtual bool deleteFileSystem(); /*! * @returns true if the file system is setup, false otherwise. */ bool fileSystemIsSetup() const; /*! * Mounts the encrypted file system. * @returns true if successful, false otherwise. */ virtual bool mountFileSystem(); /*! * Unmounts the encrypted file system. * @returns true if successful, false otherwise. */ virtual bool unmountFileSystem(); /*! * @returns true if the file system is mounted, false otherwise. */ bool fileSystemIsMounted() const; /*! * @returns the path of the mounted file system. */ virtual QString fileSystemMountPath() const; /*! * @returns the list of files which need to be backed up. */ virtual QStringList backupFiles() const; /*! * @attention if the file system is not mounted and the encryption key can * access it, this method will cause the file system to be mounted. * @returns whether the key @key is occupying a keyslot in the encrypted * file system. */ virtual bool encryptionKeyInUse(const SignOn::Key &key); /*! * Adds an encryption key to one of the available keyslots of the LUKS * partition's header. * @sa encryptionKeyInUse() * @param key The key to be added/set. * @param existingKey An already existing key. * @returns true if succeeded, false otherwise. */ virtual bool addEncryptionKey(const SignOn::Key &key, const SignOn::Key &existingKey); /*! * Releases an existing used keyslot in the LUKS partition's header. * @param key The key to be removed. * @param remainingKey Another valid key * @attention The system cannot remain keyless. * @returns true if succeeded, false otherwise. */ virtual bool removeEncryptionKey(const SignOn::Key &key, const SignOn::Key &remainingKey); Q_SIGNALS: void fileSystemMounted(); void fileSystemUnmounting(); protected: void setFileSystemMounted(bool isMounted); void setFileSystemSetup(bool isSetup); private: AbstractCryptoManagerPrivate *d_ptr; Q_DECLARE_PRIVATE(AbstractCryptoManager) }; } //namespace #endif // SIGNON_ABSTRACT_CRYPTO_MANAGER_H signond-nicolasfella/lib/signond/SignOn/abstract-key-authorizer.cpp0000664000175000017500000000406714615454535025761 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "abstract-key-authorizer.h" using namespace SignOn; namespace SignOn { class AbstractKeyAuthorizerPrivate { Q_DECLARE_PUBLIC(AbstractKeyAuthorizer) public: AbstractKeyAuthorizerPrivate(KeyHandler *keyHandler, AbstractKeyAuthorizer *authorizer); ~AbstractKeyAuthorizerPrivate() {}; private: mutable AbstractKeyAuthorizer *q_ptr; KeyHandler *m_keyHandler; }; }; AbstractKeyAuthorizerPrivate::AbstractKeyAuthorizerPrivate( KeyHandler *keyHandler, AbstractKeyAuthorizer *authorizer): q_ptr(authorizer), m_keyHandler(keyHandler) { } AbstractKeyAuthorizer::AbstractKeyAuthorizer(KeyHandler *keyHandler, QObject *parent): QObject(parent), d_ptr(new AbstractKeyAuthorizerPrivate(keyHandler, this)) { } AbstractKeyAuthorizer::~AbstractKeyAuthorizer() { delete d_ptr; } KeyHandler *AbstractKeyAuthorizer::keyHandler() const { Q_D(const AbstractKeyAuthorizer); return d->m_keyHandler; } void AbstractKeyAuthorizer::queryKeyAuthorization(const SignOn::Key &key, Reason reason) { Q_UNUSED(reason); emit keyAuthorizationQueried(key, Denied); } signond-nicolasfella/lib/signond/SignOn/abstract-key-authorizer.h0000664000175000017500000000674514615454535025433 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNON_ABSTRACT_KEY_AUTHORIZER_H #define SIGNON_ABSTRACT_KEY_AUTHORIZER_H #include "SignOn/abstract-key-manager.h" #include "SignOn/key-handler.h" #include namespace SignOn { class AbstractKeyAuthorizerPrivate; /*! * @class AbstractKeyAuthorizer * @brief Object holding the keys to the secure storage * * The AbstractKeyAuthorizer is where all keys to the secure storage are held. * It provides signals to notify when keys are inserted, authorized, removed, * disabled, as well as methods to authorize and unauthorize keys. */ class SIGNON_EXPORT AbstractKeyAuthorizer: public QObject { Q_OBJECT public: enum Result { Denied = 0, /*!< Key should not be added to the keyring */ Approved, /*!< Key can be added to the keyring */ Exclusive, /*!< Key can be set as the only key in the ring */ }; /*! * @enum Reason * Flags specifying why signond is asking for authorizing a key. * @sa queryKeyAuthorization */ enum Reasons { SystemStarted = 1 << 0, KeyInserted = 1 << 1, StorageNeeded = 1 << 2, }; Q_DECLARE_FLAGS(Reason, Reasons); /*! * Constructor */ explicit AbstractKeyAuthorizer(KeyHandler *keyHandler, QObject *parent = 0); /*! * Destructor */ virtual ~AbstractKeyAuthorizer(); /*! * @returns the KeyHandler object. */ KeyHandler *keyHandler() const; /*! * This method is called by signond when a decision needs to be taken * on whether @key should be added to the list of keys authorized to * access the secure storage. * The result is delivered asynchronously through the * keyAuthorizationQueried() signal. * @note This method doesn't effectively add @key to the secure storage * keyring; it simply asks whether @key should be authorized or not. * * @param key The key for which authorization is asked. * @sa keyAuthorizationQueried() */ virtual void queryKeyAuthorization(const SignOn::Key &key, Reason reason); Q_SIGNALS: /*! * Emitted to deliver an asynchronous response to the * queryKeyAuthorization() method. * @param key The key whose authorization has been queried. * @param result The result of the query, as specified by the Result enum. */ void keyAuthorizationQueried(const SignOn::Key key, int result); private: AbstractKeyAuthorizerPrivate *d_ptr; Q_DECLARE_PRIVATE(AbstractKeyAuthorizer) }; } // namespace #endif // SIGNON_ABSTRACT_KEY_AUTHORIZER_H signond-nicolasfella/lib/signond/SignOn/abstract-key-manager.cpp0000664000175000017500000000272614615454535025177 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "abstract-key-manager.h" using namespace SignOn; AbstractKeyManager::AbstractKeyManager(QObject *parent): QObject(parent) { } AbstractKeyManager::~AbstractKeyManager() { } void AbstractKeyManager::authorizeKey(const Key &key, const QString &message) { Q_UNUSED(message); emit keyAuthorized(key, false); } void AbstractKeyManager::queryKeys() { emit keyInserted(QByteArray()); } QString AbstractKeyManager::describeKey(const Key &key) { Q_UNUSED(key); return QString(); } bool AbstractKeyManager::supportsKeyAuthorization() const { return false; } signond-nicolasfella/lib/signond/SignOn/abstract-key-manager.h0000664000175000017500000001321414615454535024636 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNON_ABSTRACT_KEY_MANAGER_H #define SIGNON_ABSTRACT_KEY_MANAGER_H #include #include #include namespace SignOn { class AbstractKeyManagerPrivate; typedef QByteArray Key; /*! * @class AbstractKeyManager * @brief Base class for KeyManager implementations. * * The AbstractKeyManager is the base class for implementing signond key * managers. A key manager is an object which signond uses to get the keys * needed to access the encrypted storage. It emits signals whenever new keys * exist, when keys are disabled or removed. For example, a simple password * based key manager would: * @li query the user for the password when queryKeys() is called. * @li emit keyInserted() whenever the user enters the password. * @li if the password automatically expires after some time, emit keyDisabled * @li if the user changes the password, emit keyInserted() with the new * passord, and keyRemoved() for the old one. */ class SIGNON_EXPORT AbstractKeyManager: public QObject { Q_OBJECT public: /*! * Constructor */ explicit AbstractKeyManager(QObject *parent = 0); /*! * Destructor */ virtual ~AbstractKeyManager(); /*! * This method initializes the key manager. Implementations can start * emitting signals during this method's execution. */ virtual void setup() = 0; /*! * Signond calls this method if a key (typically a new key emitted with * the keyInserted() signal) needs to be authorized. Authorizing a key * means allowing the key to be used to mount the secure storage. The base * implementation of this method just emits the keyAuthorized() signal * denying the authorization, but specific implementations could delegate * the authorization to the user. * @param key The key that needs authorization. * @param message An optional message that might be shown to the user. * * @deprecated This method is deprecated and should not be * used or implemented in subclasses. */ virtual void authorizeKey(const Key &key, const QString &message = QString()); /*! * Signond calls this method when there are no active keys. This might * happen when signond is just starting, or when all existing keys have * been disabled (which would cause the secure storage to be unmounted). * The key manager must emit keyInserted() in response to this * call, either with a valid key or with an empty one. */ virtual void queryKeys(); /*! * Gets a description for the key. * @param key The key whose name is to be returned * @return A description or name that could be shown to the user to * identify the key */ virtual QString describeKey(const Key &key); /*! * @returns Whether the extension is able to authorize keys or not. * The default implementation just returns false. * * @deprecated This method is deprecated and should not be * used or implemented in subclasses. */ virtual bool supportsKeyAuthorization() const; Q_SIGNALS: /*! * Emitted when a new key is available. If the key is not yet known to * signond, signond will call authorizeKey on the key managers before * accepting it. * @param key The new key */ void keyInserted(const SignOn::Key key); /*! * Emitted when a key is disabled. For instance, this signal can be * emitted when a password expires or when a hardware key is removed. * @param key The key which has been disabled */ void keyDisabled(const SignOn::Key key); /*! * Emitted when a key is to be removed. This means that the key will never * be used again to access the secure storage; if it will be inserted * again, it will have to be re-authenticated. * It is not necessary to emit keyDisabled() before keyRemoved(): the key * will be disabled anyway when keyRemoved is emitted. * @param key The key which has to be removed */ void keyRemoved(const SignOn::Key key); /*! * The key manager emits this when it has decided whether to authorized * the key. If more than one key manager is installed, signond will * authorized the key as soon as the first key manager emits this signal * with authorized set to true. * @param key The key which underwent the authorization step * @param authorized The result of the authorization * * @deprecated This signal is deprecated and should not be * used or emitted in subclasses. */ void keyAuthorized(const SignOn::Key key, bool authorized); private: AbstractKeyManagerPrivate *d; }; } // namespace #endif // SIGNON_ABSTRACT_KEY_MANAGER_H signond-nicolasfella/lib/signond/SignOn/abstract-secrets-storage.cpp0000664000175000017500000000514414615454535026106 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2011 Canonical Ltd. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "abstract-secrets-storage.h" #include "debug.h" using namespace SignOn; namespace SignOn { class AbstractSecretsStoragePrivate { Q_DECLARE_PUBLIC(AbstractSecretsStorage) public: AbstractSecretsStoragePrivate(AbstractSecretsStorage *secretsStorage); ~AbstractSecretsStoragePrivate() {}; private: mutable AbstractSecretsStorage *q_ptr; bool m_isOpen; CredentialsDBError m_lastError; }; }; AbstractSecretsStoragePrivate::AbstractSecretsStoragePrivate( AbstractSecretsStorage *secretsStorage): q_ptr(secretsStorage), m_isOpen(false) { } AbstractSecretsStorage::AbstractSecretsStorage(QObject *parent): QObject(parent), d_ptr(new AbstractSecretsStoragePrivate(this)) { } AbstractSecretsStorage::~AbstractSecretsStorage() { delete d_ptr; } bool AbstractSecretsStorage::close() { setIsOpen(false); return true; } bool AbstractSecretsStorage::isOpen() const { return d_ptr->m_isOpen; } bool AbstractSecretsStorage::checkPassword(const quint32 id, const QString &username, const QString &password) { QString storedUsername, storedPassword; if (!loadCredentials(id, storedUsername, storedPassword)) return false; return storedUsername == username && storedPassword == password; } CredentialsDBError AbstractSecretsStorage::lastError() const { return d_ptr->m_lastError; } void AbstractSecretsStorage::clearError() { d_ptr->m_lastError.clear(); } void AbstractSecretsStorage::setIsOpen(bool isOpen) { d_ptr->m_isOpen = isOpen; } void AbstractSecretsStorage::setLastError(const CredentialsDBError &error) { d_ptr->m_lastError = error; } signond-nicolasfella/lib/signond/SignOn/abstract-secrets-storage.h0000664000175000017500000001413614615454535025554 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2011 Canonical Ltd. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_ABSTRACT_SECRETS_STORAGE_H #define SIGNON_ABSTRACT_SECRETS_STORAGE_H #include #include #include namespace SignOn { class SIGNON_EXPORT CredentialsDBError { public: enum ErrorType { NoError, NotOpen, /*!< The DB is not open */ ConnectionError, /*!< The DB is disconnected */ StatementError, /*!< The last command failed */ UnknownError }; CredentialsDBError(const QString &text = QString(), ErrorType type = NoError) { m_text = text; m_type = type; } ~CredentialsDBError() {}; void setType(ErrorType type) { m_type = type; } void setText(const QString &text) { m_text = text; } void clear() { m_type = NoError; m_text.clear(); } QString text() const { return m_text; } ErrorType type() const { return m_type; } bool isValid() const { return m_type != NoError; } private: QString m_text; ErrorType m_type; }; class AbstractSecretsStoragePrivate; /*! * @class AbstractSecretsStorage * @headerfile SignOn/abstract-secrets-storage.h SignOn/AbstractSecretsStorage * @brief Interface for secrets storage implementations. * * @ingroup Accounts_and_SSO_Framework */ class SIGNON_EXPORT AbstractSecretsStorage: public QObject { public: /*! * Constructor. * @param parent Parent object. */ explicit AbstractSecretsStorage(QObject *parent = 0); ~AbstractSecretsStorage(); /*! * Initializes and opens the secrets DB. The implementation should take * care of creating the DB, if it doesn't exist. * @param configuration A dictionary of configuration options, dependent on * the specific SecretsStorage implementation. * @returns true if successful, false otherwise. */ virtual bool initialize(const QVariantMap &configuration) = 0; /*! * Closes the secrets DB. To reopen it, call initialize(). * @returns true if successful, false otherwise. */ virtual bool close(); bool isOpen() const; /*! * Removes all stored secrets. * @returns true if successful, false otherwise. */ virtual bool clear() = 0; /*! * Stores/updates the credentials for the given identity. * @param id the identity whose credentials are being updated. * @param username the username. * @param password the password. * @returns true if successful, false otherwise. */ virtual bool updateCredentials(const quint32 id, const QString &username, const QString &password) = 0; /*! * Remove the credentials for the given identity. * @param id the identity whose credentials are being deleted. * @returns true if successful, false otherwise. */ virtual bool removeCredentials(const quint32 id) = 0; /*! * Loads the credentials. * @param id the identity whose credentials are being loaded. * @param username string for holding the loaded username. * @param password string for holding the loaded password. * @returns true if successful, false otherwise. */ virtual bool loadCredentials(const quint32 id, QString &username, QString &password) = 0; /*! * Checks whether the given username and passwords are correct for the * given identity. * @param id the identity whose credentials are being checked. * @param username the username. * @param password the password. * @returns true if username and password match. */ virtual bool checkPassword(const quint32 id, const QString &username, const QString &password); /*! * Loads extra secret data. * @param id the identity whose data are being loaded. * @param method the authentication method the data is used for. * @returns a dictionary with the data. */ virtual QVariantMap loadData(quint32 id, quint32 method) = 0; /*! * Stores extra secret data. Calling this method replaces any data which * was previously stored for the given id/method. * @param id the identity whose data are being stored. * @param method the authentication method the data is used for. * @param data a dictionary with the data. * @returns true if successful, false otherwise. */ virtual bool storeData(quint32 id, quint32 method, const QVariantMap &data) = 0; /*! * Removed extra secret data. * @param id the identity whose data are being removed. * @param method the authentication method the data is used for. * @returns true if successful, false otherwise. */ virtual bool removeData(quint32 id, quint32 method) = 0; /*! * Get the last error. */ CredentialsDBError lastError() const; /*! * Clear the last error. */ void clearError(); protected: void setIsOpen(bool isOpen); void setLastError(const CredentialsDBError &error); private: AbstractSecretsStoragePrivate *d_ptr; Q_DECLARE_PRIVATE(AbstractSecretsStorage) }; } // namespace #endif // SIGNON_ABSTRACT_SECRETS_STORAGE_H signond-nicolasfella/lib/signond/SignOn/debug.cpp0000664000175000017500000000207614615454535022262 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "debug.h" using namespace SignOn; SIGNON_EXPORT int signonLoggingLevel = 1; // criticals namespace SignOn { SIGNON_EXPORT void setLoggingLevel(int level) { signonLoggingLevel = level; } }; // namespace signond-nicolasfella/lib/signond/SignOn/debug.h0000664000175000017500000000365414615454535021732 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_DEBUG_H #define SIGNON_DEBUG_H #include #ifdef SIGNON_TRACE #ifdef TRACE #undef TRACE #endif #ifdef BLAME #undef BLAME #endif #include #ifdef DEBUG_ENABLED /* 0 - fatal, 1 - critical(default), 2 - info/debug */ extern int signonLoggingLevel; static inline bool debugEnabled() { return signonLoggingLevel >= 2; } static inline bool criticalsEnabled() { return signonLoggingLevel >= 1; } #define TRACE() \ if (debugEnabled()) qDebug() << __FILE__ << __LINE__ << __func__ #define BLAME() \ if (criticalsEnabled()) qCritical() << __FILE__ << __LINE__ << __func__ #else static inline bool debugEnabled() { return false; } static inline bool criticalsEnabled() { return false; } #define TRACE() while (0) qDebug() #define BLAME() while (0) qDebug() #endif #endif namespace SignOn { void setLoggingLevel(int level); }; #endif // SIGNON_DEBUG_H signond-nicolasfella/lib/signond/SignOn/export.h0000664000175000017500000000214214615454535022154 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_EXPORT_H #define SIGNON_EXPORT_H #include #ifdef SIGNON_EXPORT # undef SIGNON_EXPORT #endif #ifdef BUILDING_SIGNON # define SIGNON_EXPORT Q_DECL_EXPORT #else # define SIGNON_EXPORT #endif #endif // SIGNON_EXPORT_H signond-nicolasfella/lib/signond/SignOn/extension-interface.cpp0000664000175000017500000000306714615454535025147 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "extension-interface.h" using namespace SignOn; AbstractKeyManager * ExtensionInterface::keyManager(QObject *parent) const { Q_UNUSED(parent); return 0; } AbstractKeyAuthorizer * ExtensionInterface2::keyAuthorizer(KeyHandler *keyHandler, QObject *parent) const { Q_UNUSED(keyHandler); Q_UNUSED(parent); return 0; } AbstractCryptoManager * ExtensionInterface3::cryptoManager(QObject *parent) const { Q_UNUSED(parent); return 0; } AbstractSecretsStorage * ExtensionInterface3::secretsStorage(QObject *parent) const { Q_UNUSED(parent); return 0; } AbstractAccessControlManager * ExtensionInterface3::accessControlManager(QObject *parent) const { Q_UNUSED(parent); return 0; } signond-nicolasfella/lib/signond/SignOn/extension-interface.h0000664000175000017500000001047414615454535024614 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010-2011 Nokia Corporation. * Copyright (C) 2011-2016 Canonical Ltd. * Copyright (C) 2011 Intel Corporation. * * Contact: Alberto Mardegan * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNON_EXTENSION_INTERFACE_H #define SIGNON_EXTENSION_INTERFACE_H #include #include #include namespace SignOn { class AbstractCryptoManager; class AbstractKeyAuthorizer; class AbstractKeyManager; class AbstractSecretsStorage; class KeyHandler; class AbstractAccessControlManager; /*! * @class ExtensionInterface. * Interface definition for signond extensions. */ class SIGNON_EXPORT ExtensionInterface { public: virtual ~ExtensionInterface() {} /*! * Gets the KeyManager object. * * @return A key manager object, or 0 if none is provided by this plugin */ virtual AbstractKeyManager *keyManager(QObject *parent = 0) const; }; /*! * @class ExtensionInterface2. * Interface definition for signond extensions. */ class SIGNON_EXPORT ExtensionInterface2: public ExtensionInterface { public: virtual ~ExtensionInterface2() {} /*! * Gets the KeyAuthorizer object. * * @return A key authorizer object, or 0 if none is provided by this plugin */ virtual AbstractKeyAuthorizer *keyAuthorizer(KeyHandler *keyHandler, QObject *parent = 0) const; }; /*! * @class ExtensionInterface3. * Interface definition for signond extensions. */ class SIGNON_EXPORT ExtensionInterface3: public ExtensionInterface2 { public: virtual ~ExtensionInterface3() {} /*! * Gets the CryptoManager object, which will be used to setup the file * system for the credentials storage. * This object is instantiated only if the value of the "CryptoManager" * setting in the signond configuration matches the plugin's * QObject::objectName(). * * @return A CryptoManager object, or 0 if none is provided by this plugin */ virtual AbstractCryptoManager *cryptoManager(QObject *parent = 0) const; /*! * Gets the SecretsStorage object, which is used to save and load the * user's secrets, as well as authentication plugins' data. * This object is instantiated only if the value of the "SecretsStorage" * setting in the signond configuration matches the plugin's * QObject::objectName(). * * @return A SecretsStorage object, or 0 if none is provided by this plugin. */ virtual AbstractSecretsStorage *secretsStorage(QObject *parent = 0) const; /*! * Gets the AbstractAccessControlManager object, which will be used to * check accesses to the credential database. * This object is instantiated only if the value of the * "AccessControlManager" setting in the signond configuration matches the * plugin's QObject::objectName(). * * @return An AbstractAccessControlManager object, or 0 if none is provided * by this plugin */ virtual AbstractAccessControlManager *accessControlManager( QObject *parent = 0) const; }; } // namespace Q_DECLARE_INTERFACE(SignOn::ExtensionInterface, "com.nokia.SingleSignOn.ExtensionInterface/1.0") Q_DECLARE_INTERFACE(SignOn::ExtensionInterface2, "com.nokia.SingleSignOn.ExtensionInterface/2.0") Q_DECLARE_INTERFACE(SignOn::ExtensionInterface3, "com.nokia.SingleSignOn.ExtensionInterface/3.0") #endif // SIGNON_EXTENSION_INTERFACE_H signond-nicolasfella/lib/signond/SignOn/key-handler.cpp0000664000175000017500000002023614615454535023375 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "abstract-crypto-manager.h" #include "debug.h" #include "key-handler.h" #include using namespace SignOn; namespace SignOn { class KeyHandlerPrivate: public QObject { Q_OBJECT Q_DECLARE_PUBLIC(KeyHandler) public: KeyHandlerPrivate(KeyHandler *handler): q_ptr(handler), m_cryptoManager(0) { } ~KeyHandlerPrivate() {} void initialize(AbstractCryptoManager *cryptoManager, const KeyManagersList &keyManagers); bool isReady() const { return m_readyKeyManagers.count() == m_keyManagers.count(); } QSet authorizedInsertedKeys() const { QSet temp = m_insertedKeys; return temp.intersect(m_authorizedKeys); } const SignOn::Key &anyAuthorizedKey() const { return *m_authorizedKeys.constBegin(); } bool authorizeKey(const SignOn::Key &key, KeyHandler::AuthorizeFlags flags); bool revokeKeyAuthorization(const SignOn::Key &key); private Q_SLOTS: void onKeyInserted(const SignOn::Key key); void onKeyDisabled(const SignOn::Key key); void onKeyRemoved(const SignOn::Key key); private: mutable KeyHandler *q_ptr; AbstractCryptoManager *m_cryptoManager; KeyManagersList m_keyManagers; KeyManagersList m_readyKeyManagers; QSet m_insertedKeys; QSet m_authorizedKeys; }; }; void KeyHandlerPrivate::initialize(AbstractCryptoManager *cryptoManager, const KeyManagersList &keyManagers) { m_cryptoManager = cryptoManager; m_keyManagers = keyManagers; if (keyManagers.isEmpty()) { TRACE() << "No key manager has been registered"; } foreach (SignOn::AbstractKeyManager *keyManager, m_keyManagers) { connect(keyManager, SIGNAL(keyInserted(const SignOn::Key)), SLOT(onKeyInserted(const SignOn::Key))); connect(keyManager, SIGNAL(keyDisabled(const SignOn::Key)), SLOT(onKeyDisabled(const SignOn::Key))); connect(keyManager, SIGNAL(keyRemoved(const SignOn::Key)), SLOT(onKeyRemoved(const SignOn::Key))); keyManager->setup(); } } bool KeyHandlerPrivate::authorizeKey(const SignOn::Key &key, KeyHandler::AuthorizeFlags flags) { Q_Q(KeyHandler); if (m_authorizedKeys.contains(key)) { BLAME() << "Key already authorized"; return true; } if (!m_cryptoManager->fileSystemIsSetup() || flags & KeyHandler::FormatStorage) { m_authorizedKeys.clear(); m_cryptoManager->setEncryptionKey(key); if (!m_cryptoManager->setupFileSystem()) { BLAME() << "Failed to setup the encrypted partition"; return false; } } else { // FS is created and we must not reformat it if (m_authorizedKeys.isEmpty()) { BLAME() << "No authorized keys: cannot add new key"; return false; } SignOn::Key authorizedKey = anyAuthorizedKey(); if (!m_cryptoManager->fileSystemIsMounted()) { m_cryptoManager->setEncryptionKey(authorizedKey); if (!m_cryptoManager->mountFileSystem()) { BLAME() << "Couldn't mount FS: cannot add new key"; return false; } } // at this point, the FS is mounted if (!m_cryptoManager->addEncryptionKey(key, authorizedKey)) { BLAME() << "Couldn't add new key"; return false; } } m_authorizedKeys.insert(key); emit q->keyAuthorized(key); return true; } bool KeyHandlerPrivate::revokeKeyAuthorization(const SignOn::Key &key) { Q_Q(KeyHandler); if (!m_cryptoManager->fileSystemIsSetup()) { TRACE() << "File system is not setup"; return false; } if (m_authorizedKeys.isEmpty()) { BLAME() << "Cannot remove key: no authorized keys"; return false; } SignOn::Key authorizedKey = anyAuthorizedKey(); if (!m_cryptoManager->fileSystemIsMounted()) { m_cryptoManager->setEncryptionKey(authorizedKey); if (!m_cryptoManager->mountFileSystem()) { BLAME() << "Couldn't mount FS: cannot remove key"; return false; } } // at this point, the FS is mounted; remove the key if (!m_cryptoManager->removeEncryptionKey(key, authorizedKey)) { BLAME() << "Failed to remove key"; return false; } TRACE() << "Key successfully removed"; m_authorizedKeys.remove(key); emit q->keyAuthorizationRevoked(key); return true; } void KeyHandlerPrivate::onKeyInserted(const SignOn::Key key) { Q_Q(KeyHandler); TRACE() << "Key inserted."; if (!isReady()) { SignOn::AbstractKeyManager *manager = qobject_cast(sender()); if (!m_readyKeyManagers.contains(manager)) { m_readyKeyManagers.append(manager); if (isReady()) emit q->ready(); } } if (key.isEmpty()) return; m_insertedKeys.insert(key); if (m_cryptoManager->fileSystemIsSetup()) { /* The `key in use` check will attempt to mount using the new key if the file system is not already mounted */ if (m_cryptoManager->encryptionKeyInUse(key)) { TRACE() << "Key already in use."; if (!m_authorizedKeys.contains(key)) m_authorizedKeys.insert(key); } } emit q->keyInserted(key); } void KeyHandlerPrivate::onKeyDisabled(const SignOn::Key key) { Q_Q(KeyHandler); TRACE() << "Key disabled."; emit q->keyDisabled(key); m_insertedKeys.remove(key); /* If no authorized inserted keys left, emit a special notification */ if (authorizedInsertedKeys().isEmpty() && m_authorizedKeys.contains(key)) { emit q->lastAuthorizedKeyRemoved(key); } } void KeyHandlerPrivate::onKeyRemoved(const SignOn::Key key) { Q_Q(KeyHandler); TRACE() << "Key removed."; // Make sure the key is disabled: onKeyDisabled(key); q->keyRemoved(key); } KeyHandler::KeyHandler(QObject *parent): QObject(parent), d_ptr(new KeyHandlerPrivate(this)) { } KeyHandler::~KeyHandler() { delete d_ptr; } void KeyHandler::initialize(AbstractCryptoManager *cryptoManager, const KeyManagersList &keyManagers) { Q_D(KeyHandler); d->initialize(cryptoManager, keyManagers); } AbstractCryptoManager *KeyHandler::cryptoManager() const { Q_D(const KeyHandler); return d->m_cryptoManager; } bool KeyHandler::isReady() const { Q_D(const KeyHandler); return d->isReady(); } QSet KeyHandler::insertedKeys() const { Q_D(const KeyHandler); return d->m_insertedKeys; } bool KeyHandler::keyIsAuthorized(const SignOn::Key &key) const { Q_D(const KeyHandler); return d->m_authorizedKeys.contains(key); } bool KeyHandler::authorizeKey(const SignOn::Key &key, AuthorizeFlags flags) { Q_D(KeyHandler); return d->authorizeKey(key, flags); } bool KeyHandler::revokeKeyAuthorization(const SignOn::Key &key) { Q_D(KeyHandler); return d->revokeKeyAuthorization(key); } bool KeyHandler::canAddKeyAuthorization() const { Q_D(const KeyHandler); return !d->m_authorizedKeys.isEmpty(); } #include "key-handler.moc" signond-nicolasfella/lib/signond/SignOn/key-handler.h0000664000175000017500000001261414615454535023043 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNON_KEY_HANDLER_H #define SIGNON_KEY_HANDLER_H #include "SignOn/abstract-key-manager.h" #include #include namespace SignOn { class AbstractCryptoManager; class KeyHandlerPrivate; typedef QList KeyManagersList; /*! * @class KeyHandler * @brief Object holding the keys to the secure storage * * The KeyHandler is where all keys to the secure storage are held. It provides * signals to notify when keys are inserted, authorized, removed, disabled, as * well as methods to authorize and unauthorize keys. */ class SIGNON_EXPORT KeyHandler: public QObject { Q_OBJECT public: enum Authorizations { None = 0, FormatStorage = 1 << 0, /*!< Formats the secure storage */ }; Q_DECLARE_FLAGS(AuthorizeFlags, Authorizations); /*! * Constructor */ explicit KeyHandler(QObject *parent = 0); /*! * Destructor */ virtual ~KeyHandler(); /*! * This method initializes the key managers. */ void initialize(AbstractCryptoManager *cryptoManager, const KeyManagersList &keyManagers); /*! * @returns The CryptoManager. */ AbstractCryptoManager *cryptoManager() const; /*! * True if all key managers have been initialized and have started * reporting their inserted keys. */ bool isReady() const; /*! * @returns the currently inserted keys. */ QSet insertedKeys() const; /*! * @param key The key to be tested. * @returns true if @key is an authorized key. */ bool keyIsAuthorized(const SignOn::Key &key) const; /*! * Add @key to the list of keys which can be used to access the secure * storage. If the KeyHandler is empty, this method will fail. * @param key The key to be authorized. * @returns true if the operation was successful. * @sa keyAuthorized() */ bool authorizeKey(const SignOn::Key &key, AuthorizeFlags flags = None); /*! * Remove @key from the list of keys which can be used to access the * secure storage. If the KeyHandler is empty, this method will fail. * @param key The key to be revoked. * @returns true if the operation was successful. * @sa keyAuthorizationRevoked() */ bool revokeKeyAuthorization(const SignOn::Key &key); /*! * Returns true if a new key can be authorized by calling authorizeKey() * without specifying the FormatStorage flag (that is, if the KeyHandler * knows other keys which can open the storage). */ bool canAddKeyAuthorization() const; Q_SIGNALS: /*! * Emitted after all key managers have been initialized and have reported * about their inserted keys. */ void ready(); /*! * Emitted when a new key is available. If the key is not yet known to * signond, signond will call authorizeKey on the key managers before * accepting it. * @param key The new key */ void keyInserted(const SignOn::Key key); /*! * Emitted when a key is disabled. For instance, this signal can be * emitted when a password expires or when a hardware key is removed. * This signal will be emitted before the action is processed by the * KeyHandler; this means that if for instance @key was an authorized key, * calling keyIsAuthorized() from this signal's handler will still return * true. * @param key The key which has been disabled */ void keyDisabled(const SignOn::Key key); /*! * One of the key managers has asked that @key be removed. This means that * the key manager will never provide the same key again, so its * authorization to open the secure storage can be revoked. * The keyDisabled() signal will always be emitted prior to this one. * @param key The key which has been removed. */ void keyRemoved(const SignOn::Key key); /*! * Emitted when a key authorization has been revoked. * @param key The key whose authorization was revoked. */ void keyAuthorizationRevoked(const SignOn::Key key); /*! * Emitted when a key has been authorized. * @param key The key which was authorized. */ void keyAuthorized(const SignOn::Key key); /*! * Emitted when the last authorized key has been removed. */ void lastAuthorizedKeyRemoved(const SignOn::Key key); private: KeyHandlerPrivate *d_ptr; Q_DECLARE_PRIVATE(KeyHandler) }; } // namespace #endif // SIGNON_KEY_HANDLER_H signond-nicolasfella/lib/signond/SignOn/misc.cpp0000664000175000017500000000416314615454535022126 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "debug.h" #include "export.h" #include "misc.h" extern "C" { #include #include #include } #include namespace SignOn { SIGNON_EXPORT bool setUserOwnership(const QString &filePath) { const char *userHomePath = QDir::homePath().toLatin1().data(); struct stat fileInfo; if (stat(userHomePath, &fileInfo) != 0) return false; QByteArray filePathArray = filePath.toLocal8Bit(); const char *filePathStr = filePathArray.constData(); if (chown(filePathStr, fileInfo.st_uid , fileInfo.st_gid) != 0) { BLAME() << "chown of" << filePathStr << "failed, errno:" << errno; return false; } return true; } SIGNON_EXPORT bool setFilePermissions(const QString &filePath, const QFile::Permissions desiredPermissions, bool keepExisting) { if (!QFile::exists(filePath)) return false; QFile::Permissions newPermissions = desiredPermissions; QFile file(filePath); QFile::Permissions initialPermissions = file.permissions(); if (keepExisting) newPermissions |= initialPermissions; if (newPermissions != initialPermissions) return file.setPermissions(newPermissions); return true; } } //SignonDaemonNS signond-nicolasfella/lib/signond/SignOn/misc.h0000664000175000017500000000253714615454535021576 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_MISC_H #define SIGNON_MISC_H #include namespace SignOn { /* Desired permissions for the files created by signond */ const QFile::Permissions signonFilePermissions = QFile::WriteUser | QFile::ReadUser; /* Sets user UID and GID for a file. */ bool setUserOwnership(const QString &filePath); bool setFilePermissions(const QString &filePath, const QFile::Permissions permissions, bool keepExisting = true); } #endif // SIGNON_MISC_H signond-nicolasfella/lib/signond/SignOn/SignOnExtension.pc.in0000664000175000017500000000052614615454547024514 0ustar coucoufcoucoufprefix=$$INSTALL_PREFIX exec_prefix=${prefix} libdir=$$INSTALL_LIBDIR includedir=${prefix}/include plugindir=$$SIGNOND_EXTENSIONS_DIR Name: SignOnExtension Description: SignOn extension development Version: $$PROJECT_VERSION Requires: Qt$${QT_MAJOR_VERSION}Core Libs: -L${libdir} -lsignon-extension Cflags: -I${includedir}/signon-extension signond-nicolasfella/lib/signond/com.nokia.SingleSignOn.Backup.xml0000664000175000017500000000110314615454535025423 0ustar coucoufcoucouf signond-nicolasfella/lib/signond/interfaces/0000775000175000017500000000000014615454535021411 5ustar coucoufcoucoufsignond-nicolasfella/lib/signond/signoncommon.h0000664000175000017500000003244114615454535022151 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2009-2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNONCOMMON_H_ #define SIGNONCOMMON_H_ #ifdef __cplusplus #include #include #define SIGNOND_STRING(s) QLatin1String(s) #define SIGNOND_BUS QDBusConnection::sessionBus() #else #define SIGNOND_STRING(s) s #define SIGNOND_BUS //TODO #endif #define SIGNOND_NEW_IDENTITY 0 #define SIGNOND_MAX_TIMEOUT 0x7FFFFFFF /* * todo: the naming convention for interfaces should be clarified * */ /* * Common DBUS definitions * */ #define SIGNOND_SERVICE_PREFIX "com.google.code.AccountsSSO.SingleSignOn" #define SIGNOND_SERVICE SIGNOND_STRING(SIGNOND_SERVICE_PREFIX) #define SIGNOND_SOCKET_FILENAME "signond/socket" /* in XDG_RUNTIME_DIR */ #define SIGNOND_DAEMON_OBJECTPATH \ SIGNOND_STRING("/com/google/code/AccountsSSO/SingleSignOn") #define SIGNOND_DAEMON_INTERFACE_C SIGNOND_SERVICE_PREFIX ".AuthService" #define SIGNOND_IDENTITY_INTERFACE_C SIGNOND_SERVICE_PREFIX ".Identity" #define SIGNOND_AUTH_SESSION_INTERFACE_C SIGNOND_SERVICE_PREFIX ".AuthSession" #define SIGNOND_DAEMON_INTERFACE \ SIGNOND_STRING(SIGNOND_DAEMON_INTERFACE_C) #define SIGNOND_IDENTITY_INTERFACE \ SIGNOND_STRING(SIGNOND_IDENTITY_INTERFACE_C) #define SIGNOND_AUTH_SESSION_INTERFACE \ SIGNOND_STRING(SIGNOND_AUTH_SESSION_INTERFACE_C) #define SIGNOND_ERR_PREFIX SIGNOND_SERVICE_PREFIX ".Error." /* * Common server/client identity info strings * */ #define SIGNOND_IDENTITY_INFO_ID SIGNOND_STRING("Id") #define SIGNOND_IDENTITY_INFO_USERNAME SIGNOND_STRING("UserName") #define SIGNOND_IDENTITY_INFO_SECRET SIGNOND_STRING("Secret") #define SIGNOND_IDENTITY_INFO_STORESECRET SIGNOND_STRING("StoreSecret") #define SIGNOND_IDENTITY_INFO_CAPTION SIGNOND_STRING("Caption") #define SIGNOND_IDENTITY_INFO_REALMS SIGNOND_STRING("Realms") #define SIGNOND_IDENTITY_INFO_AUTHMETHODS SIGNOND_STRING("AuthMethods") #define SIGNOND_IDENTITY_INFO_OWNER SIGNOND_STRING("Owner") #define SIGNOND_IDENTITY_INFO_ACL SIGNOND_STRING("ACL") #define SIGNOND_IDENTITY_INFO_TYPE SIGNOND_STRING("Type") #define SIGNOND_IDENTITY_INFO_REFCOUNT SIGNOND_STRING("RefCount") #define SIGNOND_IDENTITY_INFO_VALIDATED SIGNOND_STRING("Validated") #define SIGNOND_IDENTITY_INFO_USERNAME_IS_SECRET \ SIGNOND_STRING("UserNameSecret") /* * Common server/client sides error names and messages * */ #define SIGNOND_UNKNOWN_ERR_STR SIGNOND_STRING("Unknown error.") #define SIGNOND_UNKNOWN_ERR_NAME SIGNOND_STRING(SIGNOND_ERR_PREFIX "Unknown") #define SIGNOND_INTERNAL_SERVER_ERR_STR \ SIGNOND_STRING("Server internal error occurred.") #define SIGNOND_INTERNAL_SERVER_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "InternalServer") #define SIGNOND_INTERNAL_COMMUNICATION_ERR_STR \ SIGNOND_STRING("Communication with the Signon service failed..") #define SIGNOND_INTERNAL_COMMUNICATION_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "InternalCommunication") #define SIGNOND_PERMISSION_DENIED_ERR_STR \ SIGNOND_STRING("Client has insufficient permissions to access the service.") #define SIGNOND_PERMISSION_DENIED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "PermissionDenied") #define SIGNOND_METHOD_OR_MECHANISM_NOT_ALLOWED_ERR_STR \ SIGNOND_STRING("Identity does not allow authentication using the selected method or mechanism.") #define SIGNOND_METHOD_OR_MECHANISM_NOT_ALLOWED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "MethodOrMechanismNotAllowed") #define SIGNOND_ENCRYPTION_FAILED_ERR_STR \ SIGNOND_STRING("Failure in encoding/decoding of incoming data") #define SIGNOND_ENCRYPTION_FAILED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "EncryptionFailed") #define SIGNOND_METHOD_NOT_KNOWN_ERR_STR \ SIGNOND_STRING("Authentication method is not known.") #define SIGNOND_METHOD_NOT_KNOWN_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "MethodNotKnown") #define SIGNOND_SERVICE_NOT_AVAILABLE_ERR_STR \ SIGNOND_STRING("Signon service is currently not available.") #define SIGNOND_SERVICE_NOT_AVAILABLE_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "ServiceNotAvailable") #define SIGNOND_INVALID_QUERY_ERR_STR \ SIGNOND_STRING("Query parameters are invalid.") #define SIGNOND_INVALID_QUERY_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "InvalidQuery") #define SIGNOND_METHOD_NOT_AVAILABLE_ERR_STR \ SIGNOND_STRING("Authentication method is not available.") #define SIGNOND_METHOD_NOT_AVAILABLE_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "MethodNotAvailable") #define SIGNOND_IDENTITY_NOT_FOUND_ERR_STR \ SIGNOND_STRING("The identity was not found on the server.") #define SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "IdentityNotFound") #define SIGNOND_STORE_FAILED_ERR_STR \ SIGNOND_STRING("Storing of the identity data failed.") #define SIGNOND_STORE_FAILED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "StoreFailed") #define SIGNOND_REMOVE_FAILED_ERR_STR \ SIGNOND_STRING("Removing identity data failed.") #define SIGNOND_REMOVE_FAILED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "RemoveFailed") #define SIGNOND_SIGNOUT_FAILED_ERR_STR SIGNOND_STRING("Signing out failed.") #define SIGNOND_SIGNOUT_FAILED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "SignOutFailed") #define SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_STR \ SIGNOND_STRING("Operation canceled by user.") #define SIGNOND_IDENTITY_OPERATION_CANCELED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "IdentityOperationCanceled") #define SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR \ SIGNOND_STRING("Query returned no results.") #define SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "CredentialsNotAvailable") #define SIGNOND_REFERENCE_NOT_FOUND_ERR_STR \ SIGNOND_STRING("Reference not found.") #define SIGNOND_REFERENCE_NOT_FOUND_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "ReferenceNotFound") #define SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_STR \ SIGNOND_STRING("Requested mechanism is not available.") #define SIGNOND_MECHANISM_NOT_AVAILABLE_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "MechanismNotAvailable") #define SIGNOND_MISSING_DATA_ERR_STR \ SIGNOND_STRING("The SessionData object does not contain all necessary information.") #define SIGNOND_MISSING_DATA_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "MissingData") #define SIGNOND_INVALID_CREDENTIALS_ERR_STR \ SIGNOND_STRING("The supplied credentials are invalid for the mechanism implementation.") #define SIGNOND_INVALID_CREDENTIALS_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "InvalidCredentials") #define SIGNOND_NOT_AUTHORIZED_ERR_STR \ SIGNOND_STRING("Not authorized to access service account.") #define SIGNOND_NOT_AUTHORIZED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "NotAuthorized") #define SIGNOND_WRONG_STATE_ERR_STR \ SIGNOND_STRING("Operation method has been called in a wrong state.") #define SIGNOND_WRONG_STATE_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "WrongState") #define SIGNOND_OPERATION_NOT_SUPPORTED_ERR_STR \ SIGNOND_STRING("The operation is not supported by the mechanism implementation.") #define SIGNOND_OPERATION_NOT_SUPPORTED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "OperationNotSupported") #define SIGNOND_NO_CONNECTION_ERR_STR SIGNOND_STRING("No network connection.") #define SIGNOND_NO_CONNECTION_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "NoConnection") #define SIGNOND_NETWORK_ERR_STR SIGNOND_STRING("Network connetion failed.") #define SIGNOND_NETWORK_ERR_NAME SIGNOND_STRING(SIGNOND_ERR_PREFIX "Network") #define SIGNOND_SSL_ERR_STR SIGNOND_STRING("Ssl connection failed.") #define SIGNOND_SSL_ERR_NAME SIGNOND_STRING(SIGNOND_ERR_PREFIX "Ssl") #define SIGNOND_RUNTIME_ERR_STR \ SIGNOND_STRING("Casting SessionData into subclass failed.") #define SIGNOND_RUNTIME_ERR_NAME SIGNOND_STRING(SIGNOND_ERR_PREFIX "Runtime") #define SIGNOND_SESSION_CANCELED_ERR_STR \ SIGNOND_STRING("Session processing was canceled.") #define SIGNOND_SESSION_CANCELED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "SessionCanceled") #define SIGNOND_TIMED_OUT_ERR_STR SIGNOND_STRING("Session processing timed out.") #define SIGNOND_TIMED_OUT_ERR_NAME SIGNOND_STRING(SIGNOND_ERR_PREFIX "TimedOut") #define SIGNOND_USER_INTERACTION_ERR_STR \ SIGNOND_STRING("User interaction dialog failed.") #define SIGNOND_USER_INTERACTION_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "UserInteraction") #define SIGNOND_OPERATION_FAILED_ERR_STR SIGNOND_STRING("Operation failed.") #define SIGNOND_OPERATION_FAILED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "OperationFailed") #define SIGNOND_TOS_NOT_ACCEPTED_ERR_STR \ SIGNOND_STRING("User declined Terms of Service.") #define SIGNOND_TOS_NOT_ACCEPTED_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "TOSNotAccepted") #define SIGNOND_FORGOT_PASSWORD_ERR_STR \ SIGNOND_STRING("User selected forgot password.") #define SIGNOND_FORGOT_PASSWORD_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "ForgotPassword") #define SIGNOND_INCORRECT_DATE_ERR_STR \ SIGNOND_STRING("The Date set is not correct") #define SIGNOND_INCORRECT_DATE_ERR_NAME \ SIGNOND_STRING(SIGNOND_ERR_PREFIX "IncorrectDate") #define SIGNOND_USER_ERROR_ERR_NAME SIGNOND_STRING(SIGNOND_ERR_PREFIX "User") #ifdef __cplusplus namespace SignOn { /*! * @enum AuthSessionState * Codes for the states of the AuthSession. * @remarks This is not a part of the public AuthSession and should be kept * as an internal enum. * This is not the same as AuthSession::AuthSessionState, it could even go * with a different name. * @todo The order of the states must be synchronized with AuthPluginState * enum */ enum AuthSessionState { SessionNotStarted = 0, /**< No message. */ HostResolving, /**< Resolving remote server host name. */ ServerConnecting, /**< Connecting to remote server. */ DataSending, /**< Sending data to remote server. */ ReplyWaiting, /**< Waiting reply from remote server. */ UserPending, /**< Waiting response from user. */ UiRefreshing, /**< Refreshing ui request. */ ProcessPending, /**< Waiting another process to start. */ SessionStarted, /**< Authentication session is started. */ ProcessCanceling, /**< Canceling.current process: */ ProcessDone, /**< Authentication completed. > */ CustomState, /**< Custom message. */ MaxState }; /* * Flag values used to inform identity clients about the server side * identity state * TODO - the DBUS signal using this will be replaced by 3 specific * signals, thus this will be removed. */ enum IdentityState { IdentityDataUpdated = 0, IdentityRemoved, IdentitySignedOut }; }// namespace SignOn #else enum SignonAuthSessionState { SIGNON_AUTH_SESSION_STATE_NOT_STARTED = 0, /**< No message. */ SIGNON_AUTH_SESSION_STATE_RESOLVING_HOST, /**< Resolving remote server host name. */ SIGNON_AUTH_SESSION_STATE_CONNECTING, /**< Connecting to remote server. */ SIGNON_AUTH_SESSION_STATE_SENDING_DATA, /**< Sending data to remote server. */ SIGNON_AUTH_SESSION_STATE_WAITING_REPLY, /**< Waiting reply from remote server. */ SIGNON_AUTH_SESSION_STATE_USER_PENDING, /**< Waiting response from user. */ SIGNON_AUTH_SESSION_STATE_UI_REFRESHING, /**< Refreshing ui request. */ SIGNON_AUTH_SESSION_STATE_PROCESS_PENDING, /**< Waiting another process to start. */ SIGNON_AUTH_SESSION_STATE_STARTED, /**< Authentication session is started. */ SIGNON_AUTH_SESSION_STATE_PROCESS_CANCELING, /**< Canceling.current process. */ SIGNON_AUTH_SESSION_STATE_PROCESS_DONE, /**< Authentication completed. */ SIGNON_AUTH_SESSION_STATE_CUSTOM, /**< Custom message. */ SIGNON_AUTH_SESSION_STATE_LAST }; #endif //__cplusplus #endif /* SIGNONCOMMON_H_ */ signond-nicolasfella/lib/signond/signond.pc.in0000664000175000017500000000036314615454535021662 0ustar coucoufcoucoufprefix=$$INSTALL_PREFIX exec_prefix=${prefix} libdir=$$INSTALL_LIBDIR includedir=${prefix}/include Name: signond-dev Description: SignOn Framework client library development package Version: $$PROJECT_VERSION Cflags: -I${includedir}/signond signond-nicolasfella/lib/signond/signond.pro0000664000175000017500000000156414615454535021457 0ustar coucoufcoucoufinclude( ../../common-project-config.pri ) include( $${TOP_SRC_DIR}/common-installs-config.pri ) include( $${TOP_SRC_DIR}/common-vars.pri ) TEMPLATE = subdirs SUBDIRS = SignOn # Input public_headers += \ signoncommon.h HEADERS = $$public_headers INCLUDEPATH += . \ $$TOP_SRC_DIR/include DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII OTHER_FILES = \ interfaces/com.google.code.AccountsSSO.SingleSignOn.AuthService.xml \ interfaces/com.google.code.AccountsSSO.SingleSignOn.AuthSession.xml \ interfaces/com.google.code.AccountsSSO.SingleSignOn.Identity.xml headers.files = $$public_headers headers.path = $${INSTALL_PREFIX}/include/signond dbus_files.files = $$OTHER_FILES dbus_files.path =$${INSTALL_PREFIX}/share/dbus-1/interfaces pkgconfig.files = signond.pc include($${TOP_SRC_DIR}/common-pkgconfig.pri) INSTALLS += headers dbus_files pkgconfig signond-nicolasfella/server/0000775000175000017500000000000014615454535016365 5ustar coucoufcoucoufsignond-nicolasfella/server/com.google.code.AccountsSSO.SingleSignOn.service.in0000664000175000017500000000014014615454535030012 0ustar coucoufcoucouf[D-BUS Service] Name=com.google.code.AccountsSSO.SingleSignOn Exec=$$INSTALL_PREFIX/bin/signond signond-nicolasfella/server/com.nokia.SingleSignOn.Backup.service.in0000664000175000017500000000013514615454535025773 0ustar coucoufcoucouf[D-BUS Service] Name=com.nokia.SingleSignOn.Backup Exec=$$INSTALL_PREFIX/bin/signond -backup signond-nicolasfella/server/com.nokia.singlesignonui.service0000664000175000017500000000010514615454535024655 0ustar coucoufcoucouf[D-BUS Service] Name=com.nokia.singlesignonui Exec=/usr/bin/signonuidsignond-nicolasfella/server/server.pro0000664000175000017500000000072114615454535020415 0ustar coucoufcoucoufinclude( ../common-project-config.pri ) include( ../common-vars.pri ) include( ../common-installs-config.pri ) TEMPLATE = subdirs QMAKE_SUBSTITUTES += com.google.code.AccountsSSO.SingleSignOn.service.in QMAKE_SUBSTITUTES += com.nokia.SingleSignOn.Backup.service.in service.path = $${INSTALL_PREFIX}/share/dbus-1/services service.files = com.google.code.AccountsSSO.SingleSignOn.service service.files += com.nokia.SingleSignOn.Backup.service INSTALLS += service signond-nicolasfella/signon.pro0000664000175000017500000000031114615454535017071 0ustar coucoufcoucoufinclude( common-vars.pri ) TEMPLATE = subdirs SUBDIRS = lib src server tests src.depends = lib tests.depends = lib src include( common-installs-config.pri ) include( doc/doc.pri ) # End of File signond-nicolasfella/src/0000775000175000017500000000000014615454535015646 5ustar coucoufcoucoufsignond-nicolasfella/src/extensions/0000775000175000017500000000000014615454535020045 5ustar coucoufcoucoufsignond-nicolasfella/src/extensions/cryptsetup/0000775000175000017500000000000014615454535022267 5ustar coucoufcoucoufsignond-nicolasfella/src/extensions/cryptsetup/crypto-handlers.cpp0000664000175000017500000004671314615454535026124 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * * Contact: Aurel Popirtac * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "crypto-handlers.h" #include "debug.h" #include "misc.h" #define SIGNON_LUKS_DEFAULT_HASH "ripemd160" #define SIGNON_LUKS_CIPHER_NAME "aes" #define SIGNON_LUKS_CIPHER_MODE "xts-plain" #define SIGNON_LUKS_CIPHER \ SIGNON_LUKS_CIPHER_NAME "-" SIGNON_LUKS_CIPHER_MODE #define SIGNON_LUKS_KEY_SIZE 256 #define SIGNON_LUKS_BASE_KEYSLOT 0 #define SIGNON_EXTERNAL_PROCESS_READ_TIMEOUT 300 #define KILO_BYTE_SIZE 1024 #define MEGA_BYTE_SIZE (KILO_BYTE_SIZE * 1024) /* ------------- SystemCommandLineCallHandler implementation -------------- */ SystemCommandLineCallHandler::SystemCommandLineCallHandler() { connect(&m_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(error(QProcess::ProcessError))); } SystemCommandLineCallHandler::~SystemCommandLineCallHandler() { } bool SystemCommandLineCallHandler::makeCall(const QString &appPath, const QStringList &args, bool readOutput) { QString trace; QTextStream stream(&trace); stream << appPath << QLatin1Char(' ') << args.join(QLatin1String(" ")); TRACE() << trace; m_process.start(appPath, args); if (!m_process.waitForStarted()) { BLAME() << "Wait for started failed"; return false; } if (readOutput) { m_output.clear(); if (m_process.waitForReadyRead(SIGNON_EXTERNAL_PROCESS_READ_TIMEOUT)) { if (!m_process.bytesAvailable()) { BLAME() << "Coult not read output of external process "; return false; } while(m_process.bytesAvailable()) m_output += m_process.readAllStandardOutput(); } } if (!m_process.waitForFinished()) { TRACE() << "Wait for finished failed"; return false; } return true; } void SystemCommandLineCallHandler::error(QProcess::ProcessError err) { TRACE() << "Process erorr:" << err; } /* ------------------ PartitionHandler implementation --------------------- */ bool PartitionHandler::createPartitionFile(const QString &fileName, const quint32 fileSize) { int fd = open(fileName.toLatin1().data(), O_RDWR | O_CREAT, 666); if (fd < 0) { BLAME() << "FAILED to create signon secure FS partition file. ERRNO:" << errno; return false; } if (ftruncate(fd, fileSize * MEGA_BYTE_SIZE) == -1) { BLAME() << "FAILED to set signon secure FS partition file size. ERRNO:" << errno; return false; } if (close(fd) < 0) TRACE() << "Failed to close secure FS partition file after creation."; if (!setFilePermissions(fileName, signonFilePermissions)) TRACE() << "Failed to set file permissions " "for the secure storage container."; return true; } bool PartitionHandler::formatPartitionFile(const QString &fileName, const quint32 fileSystemType) { QString mkfsApp = QString::fromLatin1("/sbin/mkfs.ext2"); switch (fileSystemType) { case Ext2: mkfsApp = QString::fromLatin1("/sbin/mkfs.ext2"); break; case Ext3: mkfsApp = QString::fromLatin1("/sbin/mkfs.ext3"); break; case Ext4: mkfsApp = QString::fromLatin1("/sbin/mkfs.ext4"); break; default: break; } SystemCommandLineCallHandler handler; return handler.makeCall( mkfsApp, QStringList() << fileName); } /* --------------------- MountHandler implementation ---------------------- */ bool MountHandler::mount(const QString &toMount, const QString &mountPath, const QString &fileSystemTtpe) { /* Mount a filesystem. */ return (::mount(toMount.toUtf8().constData(), mountPath.toUtf8().constData(), fileSystemTtpe.toUtf8().constData(), MS_SYNCHRONOUS | MS_NOEXEC, NULL) == 0); } bool MountHandler::umount(const QString &mountPath) { /* Unmount a filesystem. */ //TODO - investigate why errno is EINVAL TRACE() << mountPath.toUtf8().constData(); int ret = ::umount2(mountPath.toUtf8().constData(), MNT_FORCE); TRACE() << ret; switch (errno) { case EAGAIN: TRACE() << "EAGAIN"; break; case EBUSY: TRACE() << "EBUSY"; break; case EFAULT: TRACE() << "EFAULT"; break; case EINVAL: TRACE() << "EINVAL"; break; case ENAMETOOLONG: TRACE() << "ENAMETOOLONG"; break; case ENOENT: TRACE() << "ENOENT"; break; case ENOMEM: TRACE() << "ENOMEM"; break; case EPERM: TRACE() << "EPERM"; break; default: TRACE() << "umount unknown error - ignoring."; } //TODO - Remove 1st, uncommend 2nd lines after the fix above. // This is tmp hack so that the tests will work. return true; //return (ret == 0); } /* ----------------------- LosetupHandler implementation ----------------------- */ bool LosetupHandler::setupDevice(const QString &deviceName, const QString &blockDevice) { SystemCommandLineCallHandler handler; return handler.makeCall( QLatin1String("/sbin/losetup"), QStringList() << deviceName << blockDevice); } QString LosetupHandler::findAvailableDevice() { SystemCommandLineCallHandler handler; QString deviceName; bool ret = handler.makeCall( QLatin1String("/sbin/losetup"), QStringList() << QLatin1String("-f"), true); deviceName = QString::fromLocal8Bit(handler.output().trimmed()); if (ret) return deviceName; return QString(); } bool LosetupHandler::releaseDevice(const QString &deviceName) { SystemCommandLineCallHandler handler; return handler.makeCall(QLatin1String("/sbin/losetup"), QStringList() << QString::fromLatin1("-d") << deviceName); } /* -------------------- CrytpsetupHandler implementation ------------------ */ /* Callbacks for the interface callbacks struct in crypt_options struct. */ static int yesDialog(char *msg) { Q_UNUSED(msg); return 0; } static void cmdLineLog(int type, char *msg) { switch (type) { case CRYPT_LOG_NORMAL: TRACE() << msg; break; case CRYPT_LOG_ERROR: TRACE() << "Error: " << msg; break; default: TRACE() << "Internal error on logging class for msg: " << msg; break; } } static void log_wrapper(int level, const char *msg, void *usrptr) { void (*xlog)(int level, char *msg) = (void (*)(int, char*)) usrptr; xlog(level, (char *)msg); } static int yesDialog_wrapper(const char *msg, void *usrptr) { int (*xyesDialog)(char *msg) = (int (*)(char*)) usrptr; return xyesDialog((char*)msg); } int crypt_luksFormatBinary(struct crypt_options *options, const char *pwd, unsigned int pwdLen) { struct crypt_device *cd = NULL; struct crypt_params_luks1 cp = { options->hash, options->align_payload }; int r; if ((r = crypt_init(&cd, options->device))) return -EINVAL; crypt_set_log_callback(cd, log_wrapper, (void*) options->icb->log); crypt_set_confirm_callback(cd, yesDialog_wrapper, (void*) options->icb->yesDialog); crypt_set_timeout(cd, options->timeout); crypt_set_password_retry(cd, options->tries); crypt_set_iterarion_time(cd, options->iteration_time ?: 1000); crypt_set_password_verify(cd, options->flags & CRYPT_FLAG_VERIFY); r = crypt_format(cd, CRYPT_LUKS1, SIGNON_LUKS_CIPHER_NAME, SIGNON_LUKS_CIPHER_MODE, NULL, NULL, options->key_size, &cp); if (r < 0) goto out; /* Add keyslot using internally stored volume key generated during format */ r = crypt_keyslot_add_by_volume_key(cd, options->key_slot, NULL, 0, pwd, pwdLen); out: crypt_free(cd); return (r < 0) ? r : 0; } bool CryptsetupHandler::formatFile(const QByteArray &key, const QString &deviceName) { struct crypt_options options; options.key_size = SIGNON_LUKS_KEY_SIZE / 8; options.key_slot = SIGNON_LUKS_BASE_KEYSLOT; char *localDeviceName = (char *)malloc(deviceName.length() + 1); Q_ASSERT(localDeviceName != NULL); strcpy(localDeviceName, deviceName.toLatin1().constData()); options.device = localDeviceName; options.cipher = SIGNON_LUKS_CIPHER; options.new_key_file = NULL; char *localKey = (char *)malloc(key.length()); Q_ASSERT(localKey != NULL); memcpy(localKey, key.constData(), key.length()); options.flags = 0; options.iteration_time = 1000; options.timeout = 0; options.align_payload = 0; static struct interface_callbacks cmd_icb; cmd_icb.yesDialog = 0; cmd_icb.log = 0; options.icb = &cmd_icb; TRACE() << "Device: [" << options.device << "]"; TRACE() << "Key size:" << key.length(); int ret = crypt_luksFormatBinary(&options, localKey, key.length()); if (ret != 0) TRACE() << "LUKS format API call result:" << ret << "." << error(); if (localDeviceName) free(localDeviceName); if (localKey) { memset(localKey, 0x00, key.length()); free(localKey); } return (ret == 0); } int crypt_luksOpenBinary(struct crypt_options *options, const char *pwd, unsigned int pwdLen) { struct crypt_device *cd = NULL; uint32_t flags = 0; int r; if ((r = crypt_init(&cd, options->device))) return -EINVAL; crypt_set_log_callback(cd, log_wrapper, (void*) options->icb->log); crypt_set_confirm_callback(cd, yesDialog_wrapper, (void*) options->icb->yesDialog); crypt_set_timeout(cd, options->timeout); crypt_set_password_retry(cd, options->tries); crypt_set_iterarion_time(cd, options->iteration_time ?: 1000); crypt_set_password_verify(cd, options->flags & CRYPT_FLAG_VERIFY); if ((r = crypt_load(cd, CRYPT_LUKS1, NULL))) { crypt_free(cd); return r; } if (options->flags & CRYPT_FLAG_READONLY) flags |= CRYPT_ACTIVATE_READONLY; if (options->flags & CRYPT_FLAG_NON_EXCLUSIVE_ACCESS) flags |= CRYPT_ACTIVATE_NO_UUID; if (options->key_file) r = -1; else r = crypt_activate_by_passphrase(cd, options->name, CRYPT_ANY_SLOT, pwd, pwdLen, flags); crypt_free(cd); return (r < 0) ? r : 0; } bool CryptsetupHandler::openFile(const QByteArray &key, const QString &deviceName, const QString &deviceMap) { struct crypt_options options; char *localDeviceMap = (char *)malloc(deviceMap.length() + 1); Q_ASSERT(localDeviceMap != NULL); strcpy(localDeviceMap, deviceMap.toLatin1().constData()); options.name = localDeviceMap; char *localDeviceName = (char *)malloc(deviceName.length() + 1); Q_ASSERT(localDeviceName != NULL); strcpy(localDeviceName, deviceName.toLatin1().constData()); options.device = localDeviceName; char *localKey = (char *)malloc(key.length()); Q_ASSERT(localKey != NULL); memcpy(localKey, key.constData(), key.length()); options.key_file = NULL; options.timeout = 0; /* Do not change this: 1) In case of failure to open, libcryptsetup code will enter infinite loop - library BUG/FEATURE. 2) There is no need for multiple tries, option is intended for command line use of the utility. */ options.tries = 0; options.flags = 0; static struct interface_callbacks cmd_icb; cmd_icb.yesDialog = yesDialog; cmd_icb.log = cmdLineLog; options.icb = &cmd_icb; TRACE() << "Device [" << options.device << "]"; TRACE() << "Map name [" << options.name << "]"; TRACE() << "Key size:" << key.length(); int ret = crypt_luksOpenBinary(&options, localKey, key.length()); if (ret != 0) TRACE() << "LUKS open API call result:" << ret << "." << error() << "."; if (localDeviceName) free(localDeviceName); if (localDeviceMap) free(localDeviceMap); if (localKey) { memset(localKey, 0x00, key.length()); free(localKey); } return (ret == 0); } bool CryptsetupHandler::closeFile(const QString &deviceMap) { struct crypt_options options; char *localDeviceMap = (char *)malloc(deviceMap.length() + 1); Q_ASSERT(localDeviceMap != NULL); strcpy(localDeviceMap, deviceMap.toLatin1().constData()); options.name = localDeviceMap; static struct interface_callbacks cmd_icb; cmd_icb.yesDialog = yesDialog; cmd_icb.log = cmdLineLog; options.icb = &cmd_icb; TRACE() << "Map name [" << options.name << "]"; int ret = crypt_remove_device(&options); if (ret != 0) TRACE() << "Cryptsetup remove API call result:" << ret << "." << error(); if (localDeviceMap) free(localDeviceMap); return (ret == 0); } bool CryptsetupHandler::removeFile(const QString &deviceName) { Q_UNUSED(deviceName); //todo - delete file system (wipe credentials storege) is based on this return false; } int crypt_luksAddKeyBinary(struct crypt_options *options, const char *pwd, unsigned int pwdLen, const char *newPwd, unsigned int newPwdLen) { struct crypt_device *cd = NULL; int r; if ((r = crypt_init(&cd, options->device))) return -EINVAL; crypt_set_log_callback(cd, log_wrapper, (void*) options->icb->log); crypt_set_confirm_callback(cd, yesDialog_wrapper, (void*) options->icb->yesDialog); crypt_set_timeout(cd, options->timeout); crypt_set_password_retry(cd, options->tries); crypt_set_iterarion_time(cd, options->iteration_time ?: 1000); crypt_set_password_verify(cd, options->flags & CRYPT_FLAG_VERIFY); if ((r = crypt_load(cd, CRYPT_LUKS1, NULL))) { crypt_free(cd); return r; } if (options->key_file || options->new_key_file) r = -1; else r = crypt_keyslot_add_by_passphrase(cd, options->key_slot, pwd, pwdLen, newPwd, newPwdLen); crypt_free(cd); return (r < 0) ? r : 0; } bool CryptsetupHandler::addKeySlot(const QString &deviceName, const QByteArray &key, const QByteArray &existingKey) { struct crypt_options options; options.key_size = SIGNON_LUKS_KEY_SIZE / 8; options.cipher = SIGNON_LUKS_CIPHER; char *localDeviceName = (char *)malloc(deviceName.length() + 1); Q_ASSERT(localDeviceName != NULL); strcpy(localDeviceName, deviceName.toLatin1().constData()); options.device = localDeviceName; options.new_key_file = NULL; options.key_file = NULL; options.key_slot = -1; options.flags = 0; options.iteration_time = 1000; options.timeout = 0; options.tries = 0; static struct interface_callbacks cmd_icb; cmd_icb.yesDialog = yesDialog; cmd_icb.log = cmdLineLog; options.icb = &cmd_icb; int ret = crypt_luksAddKeyBinary(&options, existingKey.constData(), existingKey.length(), key.constData(), key.length()); if (localDeviceName) free(localDeviceName); if (ret != 0) TRACE() << "Cryptsetup add key API call result:" << ret << "." << error(); return (ret == 0); } int crypt_luksRemoveKeyBinary(struct crypt_options *options, const char *pwdToRemove, unsigned int pwdToRemoveLen) { struct crypt_device *cd = NULL; int key_slot; int r; if ((r = crypt_init(&cd, options->device))) return -EINVAL; crypt_set_log_callback(cd, log_wrapper, (void*) options->icb->log); crypt_set_confirm_callback(cd, yesDialog_wrapper, (void*) options->icb->yesDialog); crypt_set_timeout(cd, options->timeout); crypt_set_password_retry(cd, options->tries); crypt_set_iterarion_time(cd, options->iteration_time ?: 1000); crypt_set_password_verify(cd, options->flags & CRYPT_FLAG_VERIFY); if ((r = crypt_load(cd, CRYPT_LUKS1, NULL))) { crypt_free(cd); return r; } if ((key_slot = crypt_keyslot_by_passphrase(cd, NULL, pwdToRemove, pwdToRemoveLen, 0, NULL)) < 0) { r = -EPERM; goto out; } r = crypt_keyslot_destroy(cd, key_slot); out: crypt_free(cd); return (r < 0) ? r : 0; } bool CryptsetupHandler::removeKeySlot(const QString &deviceName, const QByteArray &key, const QByteArray &remainingKey) { struct crypt_options options; options.key_size = SIGNON_LUKS_KEY_SIZE / 8; options.cipher = SIGNON_LUKS_CIPHER; char *localDeviceName = (char *)malloc(deviceName.length() + 1); Q_ASSERT(localDeviceName != NULL); strcpy(localDeviceName, deviceName.toLatin1().constData()); options.device = localDeviceName; options.new_key_file = NULL; options.key_file = NULL; options.key_slot = -1; options.flags = 0; options.timeout = 0; static struct interface_callbacks cmd_icb; cmd_icb.yesDialog = yesDialog; cmd_icb.log = cmdLineLog; options.icb = &cmd_icb; int ret = crypt_luksRemoveKeyBinary(&options, key.constData(), key.length()); if (localDeviceName) free(localDeviceName); if (ret != 0) TRACE() << "Cryptsetup remove key API call result:" << ret << "." << error(); return (ret == 0); } bool CryptsetupHandler::loadDmMod() { SystemCommandLineCallHandler handler; return handler.makeCall( QLatin1String("/sbin/modprobe"), QStringList() << QString::fromLatin1("dm_mod")); } QString CryptsetupHandler::error() { char buf[260]; crypt_get_error(buf, 256); return QString::fromLocal8Bit(buf); } signond-nicolasfella/src/extensions/cryptsetup/crypto-handlers.h0000664000175000017500000001717614615454535025572 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2011 Nokia Corporation. * * Contact: Aurel Popirtac * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @file cryptohandlers.h * Definition of the CryptsetupHandler object. * @ingroup Accounts_and_SSO_Framework */ #ifndef SIGNON_CRYPTSETUP_HANDLER_H #define SIGNON_CRYPTSETUP_HANDLER_H #include #include #include /*! * @class SystemCommandLineCallHandler * Handles calls to system command line tools */ class SystemCommandLineCallHandler: public QObject { Q_OBJECT public: /*! * Basic constructor */ SystemCommandLineCallHandler(); /*! * Destructor */ ~SystemCommandLineCallHandler(); /*! * Executes the application at appPath in a separate child process. * @param appPath Path of the application to be executed. * @param args List of arguments for the executed application. * @param readOutput Flag whether to save or not the std::out output of the * executed application. * @returns true upon success, false otherwise. */ bool makeCall(const QString &appPath, const QStringList &args, bool readOutput = false); /*! * @returns the raw untrimmed output of the last process called with * makeCall and readOutput set to true */ QByteArray output() const { return m_output; } private Q_SLOTS: void error(QProcess::ProcessError err); private: QProcess m_process; QByteArray m_output; Q_DISABLE_COPY(SystemCommandLineCallHandler); }; /*! * @class MountHandler * Handles mounting and unmounting of file systems */ struct PartitionHandler { enum { Ext2 = 0, Ext3, Ext4 }; /*! * Creates a random data file of fileSize Mb. * @param fileName The name of the file to be created. * @param fileSize The size of the file to be created (Mb) */ static bool createPartitionFile(const QString &fileName, const quint32 fileSize); /*! * Formats a file (block device) for a specific file system type * (ext2,ext3,ext4) * @param fileName Name of the file to be formatted. * @param fileSystemType Type of the file syste * @returns true upon success, false otherwise. */ static bool formatPartitionFile(const QString &fileName, const quint32 fileSystemType); private: /*! * Construction and copying disabled. */ PartitionHandler(); Q_DISABLE_COPY(PartitionHandler) }; /*! * @class MountHandler */ struct MountHandler { /*! * Mounts a block device to a specific location. * @param toMount File system to be mounted. * @param mounthPath Path to where the file system will be mounted. * @param fileSystemType The type of the file system to be mounted. * @returns true upon success, false otherwise. */ static bool mount(const QString &source, const QString &target, const QString &fileSystemType = QLatin1String("ext2")); /*! * Unmounts a block device from a specific location. * @param mounthPath Path of the file system to be unmounted. * @returns true upon success, false otherwise. */ static bool umount(const QString &target); private: /*! * Construction and copying disabled. */ MountHandler(); Q_DISABLE_COPY(MountHandler) }; /*! * @class LosetupHandler * Handles mounting, unmounting of loopback devices. * Also helps finding unused loopback devices. */ struct LosetupHandler { /*! * Mounts a block device to loopback device. * @param deviceName Loopback device to pe set up. * @param blockDevice Block device to be loopback mounted. */ static bool setupDevice(const QString &deviceName, const QString &blockDevice); /*! * Finds an available loopback device. * @return the name of a spare device or a null string if none found. */ static QString findAvailableDevice(); /*! * Releases a used loopback device. * @param deviceName Loopback device to be released * @returns true upon success, false otherwise */ static bool releaseDevice(const QString &deviceName); private: /*! * Construction and copying disabled. */ LosetupHandler(); Q_DISABLE_COPY(LosetupHandler) }; /*! * @class CryptsetupHandler * Wraps the libcryptsetup API functionality. * @ingroup Accounts_and_SSO_Framework */ struct CryptsetupHandler { /*! * Formats the file system. * @param key, key of the ecrypted file system * @param deviceName, name of the loop device LUKS formatted. */ static bool formatFile(const QByteArray &key, const QString &deviceName); /*! * Opens the file system. * @param key, key of the ecrypted file system * @param deviceName, name of the loop device to be opened. * @param deviceMap, name of the device mapper mapped device. */ static bool openFile(const QByteArray &key, const QString &deviceName, const QString &deviceMap); /*! * Closes the file system. * @param deviceName, name of the mapped device to be closed. */ static bool closeFile(const QString &deviceName); /*! * Removes the file system. * @param deviceName, name of the device. * @todo implement this */ static bool removeFile(const QString &deviceName); /*! * Adds a key to a free encryption header slot. This operation is to be * executed if at least one key is already set in the LUKS header. * @param deviceName, name of the device. * @param key, the key to be added. * @param existingKey, an already existing key. * @returns whether the key was successfully added or not. * @todo implement this */ static bool addKeySlot(const QString &deviceName, const QByteArray &key, const QByteArray &existingKey); /*! * Removes a key ocupying an encryption header slot * @param deviceName, name of the device. * @param key, the key to be removed. * @returns whether the key was successfully removed or not. * @todo implement this */ static bool removeKeySlot(const QString &deviceName, const QByteArray &key, const QByteArray &remainingKey); /*! * Loads the `dm_mod` kernel module * @returns whether the dm_mod was successfully loaded or not. */ static bool loadDmMod(); /*! * @returns the last error as string. */ static QString error(); private: /*! * Construction and copying disabled. */ CryptsetupHandler(); Q_DISABLE_COPY(CryptsetupHandler) }; #endif // SIGNON_CRYPTSETUP_HANDLER_H signond-nicolasfella/src/extensions/cryptsetup/crypto-manager.cpp0000664000175000017500000003525414615454535025734 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * * Contact: Aurel Popirtac * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "crypto-manager.h" #include "crypto-handlers.h" #include "debug.h" #include "misc.h" #include #include #include #include #define DEVICE_MAPPER_DIR "/dev/mapper/" #define EXT2 "ext2" #define EXT3 "ext3" #define EXT4 "ext4" const uint CryptoManager::signonMinumumDbSize = 8; const char CryptoManager::signonDefaultFileSystemName[] = "signonfs"; const char CryptoManager::signonDefaultFileSystemType[] = EXT2; const QString CryptoManager::keychainFilePath() const { return m_fileSystemMountPath + QDir::separator() + QLatin1String("keychain"); } void CryptoManager::addKeyToKeychain(const QByteArray &key) const { //If key is already present do not add it - backwards compat. feature if (keychainContainsKey(key)) return; QSettings keychain(keychainFilePath(), QSettings::IniFormat); int keyCount = keychain.allKeys().count(); keychain.setValue(QString::number(++keyCount), QVariant(key)); } void CryptoManager::removeKeyFromKeychain(const QByteArray &key) const { QSettings keychain(keychainFilePath(), QSettings::IniFormat); foreach (QString keyIt, keychain.allKeys()) { if (keychain.value(keyIt).toByteArray() == key) { keychain.remove(keyIt); break; } } } bool CryptoManager::keychainContainsKey(const QByteArray &key) const { QSettings keychain(keychainFilePath(), QSettings::IniFormat); foreach (QString keyIt, keychain.allKeys()) { if (keychain.value(keyIt).toByteArray() == key) return true; } return false; } CryptoManager::CryptoManager(QObject *parent): SignOn::AbstractCryptoManager(parent), m_fileSystemPath(QString()), m_fileSystemMapPath(QString()), m_fileSystemName(QString()), m_fileSystemMountPath(QString()), m_loopDeviceName(QString()), m_fileSystemType(Ext2), m_fileSystemSize(4) { updateMountState(Unmounted); if (!CryptsetupHandler::loadDmMod()) BLAME() << "Could not load `dm_mod`!"; } CryptoManager::~CryptoManager() { unmountFileSystem(); } bool CryptoManager::initialize(const QVariantMap &configuration) { QString storagePath = QDir(configuration.value(QLatin1String("StoragePath")).toString()).path(); if (storagePath.startsWith(QLatin1Char('~'))) storagePath.replace(0, 1, QDir::homePath()); QString encryptedFSPath = storagePath + QDir::separator() + QLatin1String(signonDefaultFileSystemName); bool isOk = false; quint32 storageSize = configuration.value(QLatin1String("Size")).toUInt(&isOk); if (!isOk || storageSize < signonMinumumDbSize) { storageSize = signonMinumumDbSize; TRACE() << "Less than minimum possible storage size configured." << "Setting to the minimum of:" << signonMinumumDbSize << "Mb"; } QString fileSystemType = configuration.value(QLatin1String("FileSystemType")).toString(); setFileSystemPath(encryptedFSPath); setFileSystemSize(storageSize); setFileSystemType(fileSystemType); checkFileSystemSetup(); return true; } void CryptoManager::setFileSystemPath(const QString &path) { m_fileSystemPath = path; QFileInfo fsFileInfo(path); m_fileSystemName = fsFileInfo.fileName(); m_fileSystemMapPath = QLatin1String(DEVICE_MAPPER_DIR) + m_fileSystemName; m_fileSystemMountPath = path + QLatin1String("-mnt"); } bool CryptoManager::setFileSystemSize(const quint32 size) { if (size < MINUMUM_ENCRYPTED_FILE_SYSTEM_SIZE) { TRACE() << "Minumum encrypted file size is 4 Mb."; return false; } m_fileSystemSize = size; return true; } bool CryptoManager::setFileSystemType(const QString &type) { QString cmpBase = type.toLower(); if (cmpBase == QLatin1String(EXT2)) { m_fileSystemType = Ext2; return true; } else if (cmpBase == QLatin1String(EXT3)) { m_fileSystemType = Ext3; return true; } else if (cmpBase == QLatin1String(EXT4)) { m_fileSystemType = Ext4; return true; } return false; } void CryptoManager::checkFileSystemSetup() { setFileSystemSetup(QFile::exists(m_fileSystemPath)); } bool CryptoManager::setupFileSystem() { if (m_mountState == Mounted) { TRACE() << "Ecrypyted file system already mounted."; return false; } if (encryptionKey().isEmpty()) { TRACE() << "No access code set. Stopping mount process."; return false; } if (!CryptsetupHandler::loadDmMod()) { BLAME() << "Could not load `dm_mod`!"; return false; } clearFileSystemResources(); m_loopDeviceName = LosetupHandler::findAvailableDevice(); if (m_loopDeviceName.isNull()) { BLAME() << "No free loop device available!"; return false; } if (!PartitionHandler::createPartitionFile(m_fileSystemPath, m_fileSystemSize)) { BLAME() << "Could not create partition file."; unmountFileSystem(); return false; } checkFileSystemSetup(); if (!LosetupHandler::setupDevice(m_loopDeviceName, m_fileSystemPath)) { BLAME() << "Failed to setup loop device:" << m_loopDeviceName; unmountFileSystem(); return false; } updateMountState(LoopSet); if (!CryptsetupHandler::formatFile(encryptionKey(), m_loopDeviceName)) { BLAME() << "Failed to LUKS format."; unmountFileSystem(); return false; } updateMountState(LoopLuksFormatted); //attempt luks close, in case of a leftover. if (QFile::exists(QLatin1String(DEVICE_MAPPER_DIR) + m_fileSystemName)) { TRACE() << "Filesystem exists, closing"; CryptsetupHandler::closeFile(m_fileSystemName); } if (!CryptsetupHandler::openFile(encryptionKey(), m_loopDeviceName, m_fileSystemName)) { BLAME() << "Failed to LUKS open"; unmountFileSystem(); return false; } updateMountState(LoopLuksOpened); if (!PartitionHandler::formatPartitionFile(m_fileSystemMapPath, m_fileSystemType)) { BLAME() << "Could not format mapped partition."; unmountFileSystem(); return false; } if (!mountMappedDevice()) { BLAME() << "Failed to mount ecrypted file system."; unmountFileSystem(); return false; } addKeyToKeychain(encryptionKey()); updateMountState(Mounted); return true; } //TODO - add checking for LUKS header in case of preavious app run formatting //failure bool CryptoManager::mountFileSystem() { if (m_mountState == Mounted) { TRACE() << "Ecrypyted file system already mounted."; return false; } if (encryptionKey().isEmpty()) { TRACE() << "No access code set. Stopping mount process."; return false; } clearFileSystemResources(); if (!CryptsetupHandler::loadDmMod()) { BLAME() << "Could not load `dm_mod`!"; return false; } m_loopDeviceName = LosetupHandler::findAvailableDevice(); if (m_loopDeviceName.isNull()) { BLAME() << "No free loop device available!"; return false; } if (!LosetupHandler::setupDevice(m_loopDeviceName, m_fileSystemPath)) { BLAME() << "Failed to setup loop device:" << m_loopDeviceName; unmountFileSystem(); return false; } updateMountState(LoopSet); //attempt luks close, in case of a leftover. if (QFile::exists(QLatin1String(DEVICE_MAPPER_DIR) + m_fileSystemName)) CryptsetupHandler::closeFile(m_fileSystemName); if (!CryptsetupHandler::openFile(encryptionKey(), m_loopDeviceName, m_fileSystemName)) { BLAME() << "Failed to LUKS open."; unmountFileSystem(); return false; } updateMountState(LoopLuksOpened); if (!mountMappedDevice()) { TRACE() << "Failed to mount ecrypted file system."; unmountFileSystem(); return false; } addKeyToKeychain(encryptionKey()); updateMountState(Mounted); return true; } void CryptoManager::clearFileSystemResources() { /* This method is a `just in case call` for the situations when signond closes whithout handling the unmounting of the secure storage. */ TRACE() << "--- START clearing secure storage possibly used resources." " Ignore possible errors. ---"; if (!unmountMappedDevice()) TRACE() << "Unmounting mapped device failed."; if (QFile::exists(QLatin1String(DEVICE_MAPPER_DIR) + m_fileSystemName)) { if (!CryptsetupHandler::closeFile(m_fileSystemName)) TRACE() << "Failed to LUKS close."; } /* TODO - find a way to check which loop device was previously used by signond and close that specific one, until then this will be skipped as it might close devices used by different processes. if (!LosetupHandler::releaseDevice(m_loopDeviceName)) { TRACE() << "Failed to release loop device."; */ TRACE() << "--- DONE clearing secure storage possibly used resources. ---"; } bool CryptoManager::unmountFileSystem() { if (m_mountState == Unmounted) { TRACE() << "Ecrypyted file system not mounted."; return true; } setFileSystemMounted(false); bool isOk = true; if ((m_mountState >= Mounted) && !unmountMappedDevice()) { TRACE() << "Failed to unmount mapped loop device."; isOk = false; } else { TRACE() << "Mapped loop device unmounted."; } if ((m_mountState >= LoopLuksOpened) && (!CryptsetupHandler::closeFile(m_fileSystemName))) { TRACE() << "Failed to LUKS close."; isOk = false; } else { TRACE() << "Luks close succeeded."; } if ((m_mountState >= LoopSet) && (!LosetupHandler::releaseDevice(m_loopDeviceName))) { TRACE() << "Failed to release loop device."; isOk = false; } else { TRACE() << "Loop device released."; } updateMountState(Unmounted); return isOk; } bool CryptoManager::deleteFileSystem() { if (m_mountState > Unmounted) { if (!unmountFileSystem()) return false; } //TODO - implement effective deletion in specific handler object return false; } QString CryptoManager::fileSystemMountPath() const { return m_fileSystemMountPath; } QStringList CryptoManager::backupFiles() const { return QStringList() << m_fileSystemPath; } void CryptoManager::updateMountState(const FileSystemMountState state) { TRACE() << "Updating mount state:" << state; if (state == m_mountState) return; m_mountState = state; setFileSystemMounted(state == Mounted); } bool CryptoManager::mountMappedDevice() { //create mnt dir if not existant if (!QFile::exists(m_fileSystemMountPath)) { QDir dir; if (!dir.mkpath(m_fileSystemMountPath)) { BLAME() << "Could not create target mount dir path."; return false; } if (!setUserOwnership(m_fileSystemMountPath)) TRACE() << "Failed to set User ownership for " "the secure storage mount target."; } MountHandler::mount(m_fileSystemMapPath, m_fileSystemMountPath); return true; } bool CryptoManager::unmountMappedDevice() { return MountHandler::umount(m_fileSystemMountPath); } bool CryptoManager::addEncryptionKey(const SignOn::Key &key, const SignOn::Key &existingKey) { /* * TODO -- limit number of stored keys to the total available slots - 1. */ if (m_mountState >= LoopLuksOpened) { if (CryptsetupHandler::addKeySlot( m_loopDeviceName, key, existingKey)) { addKeyToKeychain(key); return true; } } TRACE() << "FAILED to occupy key slot on the encrypted file system header."; return false; } bool CryptoManager::removeEncryptionKey(const SignOn::Key &key, const SignOn::Key &remainingKey) { if (m_mountState >= LoopLuksOpened) { if (CryptsetupHandler::removeKeySlot( m_loopDeviceName, key, remainingKey)) removeKeyFromKeychain(key); return true; } TRACE() << "FAILED to release key slot from the encrypted file system " "header."; return false; } bool CryptoManager::encryptionKeyInUse(const SignOn::Key &key) { if (fileSystemIsMounted() && (encryptionKey() == key)) return true; if(!fileSystemIsMounted()) { setEncryptionKey(key); return mountFileSystem(); } /* Variant that tests if the key is in the LUKS keychain * by using a file on the encrypted storage containing the keychain. */ return keychainContainsKey(key); /* * Variant that tests if the key is in the LUKS keychain * by directly accessing the LUKS system * * QByteArray dummyKey("dummy"); * if (addEncryptionKey(dummyKey, key)) { * if (!removeEncryptionKey(dummyKey, key)) * BLAME() << "Could not remove dummy auxiliary key " * "from encrypted file system header."; * return true; * } * * return false; */ } //TODO - remove this after stable version is achieved. void CryptoManager::serializeData() { TRACE() << "m_accessCode" << encryptionKey(); TRACE() << "m_fileSystemPath" << m_fileSystemPath; TRACE() << "m_fileSystemMapPath" << m_fileSystemMapPath; TRACE() << "m_fileSystemName" << m_fileSystemName; TRACE() << "m_loopDeviceName" << m_loopDeviceName; TRACE() << "m_fileSystemType" << m_fileSystemType; TRACE() << "m_fileSystemSize" << m_fileSystemSize; } signond-nicolasfella/src/extensions/cryptsetup/crypto-manager.h0000664000175000017500000001326114615454535025373 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2011 Nokia Corporation. * * Contact: Aurel Popirtac * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @file cryptomanager.h * Definition of the CryptoManager object. * @ingroup Accounts_and_SSO_Framework */ #ifndef SIGNON_CRYPTO_MANAGER_H #define SIGNON_CRYPTO_MANAGER_H #include #include #define MINUMUM_ENCRYPTED_FILE_SYSTEM_SIZE 4 /*! * @class CryptoManager * Encrypted file system manager. Uses cryptsetup and LUKS. * @ingroup Accounts_and_SSO_Framework */ class CryptoManager: public SignOn::AbstractCryptoManager { Q_OBJECT // DO NOT change the order of the enum values!!! enum FileSystemMountState { Unmounted = 0, LoopSet, LoopLuksFormatted, LoopLuksOpened, Mounted }; static const uint signonMinumumDbSize; static const char signonDefaultFileSystemName[]; static const char signonDefaultFileSystemType[]; public: // reimplemented virtual methods bool initialize(const QVariantMap &configuration); /*! * @enum FileSystemType * Supported encrypted partion filesystem type. */ enum FileSystemType { Ext2 = 0, Ext3, Ext4 }; /*! * Constructs a CryptoManager object with the given parent. * @param parent */ CryptoManager(QObject *parent = 0); /*! * Destroys a CryptoManager object. */ ~CryptoManager(); /*! * Sets up an encrypted file system. This method is to be called only at * the file system creation/formatting. * Use mountFileSystem() on subsequent uses. This method handles also the * mounting so when using it, a call * to mountFileSystem() is not necessary. * @returns true, if successful, false otherwise. * @warning this method will always format the file system, use carefully. */ bool setupFileSystem(); /*! * Deletes the encrypted file system. * @returns true, if successful, false otherwise. * @warning use this carefully, this will lead to data loss. * @todo finish implemetation. */ bool deleteFileSystem(); /*! * Mounts the encrypted file system. * @returns true, if successful, false otherwise. */ bool mountFileSystem(); /*! * Unmounts the encrypted file system. * @returns true, if successful, false otherwise. */ bool unmountFileSystem(); /*! * @returns the path of the mounted file system. */ QString fileSystemMountPath() const; /*! * @returns the list of files which need to be backed up. */ QStringList backupFiles() const; /*! * @attention if the file system is not mounted and the encryption * key can access it, this method will cause the file system to be * mounted. * @returns whether the key `key` is occupying a keyslot in the encrypted * file system. */ bool encryptionKeyInUse(const SignOn::Key &key); /*! * Adds an encryption key to one of the available keyslots of the LUKS * partition's header. * Use the `keyTag` parameter in order to store and keep track of the key. * @sa isEncryptionKey(const SignOn::Key &key) * @param key The key to be added/set. * @param existingKey An already existing key. * @returns true, if succeeded, false otherwise. */ bool addEncryptionKey(const SignOn::Key &key, const SignOn::Key &existingKey); /*! * Releases an existing used keyslot in the LUKS partition's header. * @param key The key to be removed. * @param remainingKey Another valid key * @attention The system cannot remain keyless. * @returns true, if succeeded, false otherwise. */ bool removeEncryptionKey(const SignOn::Key &key, const SignOn::Key &remainingKey); private: bool setFileSystemType(const QString &type); bool setFileSystemSize(const quint32 size); void setFileSystemPath(const QString &path); void checkFileSystemSetup(); void clearFileSystemResources(); bool mountMappedDevice(); bool unmountMappedDevice(); void updateMountState(const FileSystemMountState state); static bool createPartitionFile(const QString &filePath); static bool formatMapFileSystem(const QString &fileSystemPath); const QString keychainFilePath() const; void addKeyToKeychain(const QByteArray &key) const; void removeKeyFromKeychain(const QByteArray &key) const; bool keychainContainsKey(const QByteArray &key) const; private: //TODO remove this void serializeData(); private: QString m_fileSystemPath; QString m_fileSystemMapPath; QString m_fileSystemName; QString m_fileSystemMountPath; QString m_loopDeviceName; FileSystemMountState m_mountState; FileSystemType m_fileSystemType; quint32 m_fileSystemSize; }; #endif // SIGNON_CRYPTOMANAGER_H signond-nicolasfella/src/extensions/cryptsetup/cryptsetup-plugin.cpp0000664000175000017500000000243214615454535026512 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * * Contact: Aurel Popirtac * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "cryptsetup-plugin.h" #include "crypto-manager.h" #include using namespace SignOn; CryptsetupPlugin::CryptsetupPlugin(): QObject(0) { setObjectName(QLatin1String("cryptsetup")); } AbstractCryptoManager *CryptsetupPlugin::cryptoManager(QObject *parent) const { qDebug() << Q_FUNC_INFO; return new CryptoManager(parent); } signond-nicolasfella/src/extensions/cryptsetup/cryptsetup-plugin.h0000664000175000017500000000264714615454535026167 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * * Contact: Aurel Popirtac * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef CRYPTSETUP_PLUGIN_H #define CRYPTSETUP_PLUGIN_H #include #include class CryptsetupPlugin: public QObject, public SignOn::ExtensionInterface3 { Q_OBJECT Q_INTERFACES(SignOn::ExtensionInterface3) Q_PLUGIN_METADATA(IID "com.nokia.SingleSignOn.ExtensionInterface/3.0") public: CryptsetupPlugin(); // reimplemented methods SignOn::AbstractCryptoManager *cryptoManager(QObject *parent = 0) const; }; #endif // CRYPTSETUP_PLUGIN_H signond-nicolasfella/src/extensions/cryptsetup/cryptsetup.pro0000664000175000017500000000133714615454535025237 0ustar coucoufcoucoufinclude( ../../../common-project-config.pri ) include( $${TOP_SRC_DIR}/common-vars.pri ) TEMPLATE = lib TARGET = cryptsetup CONFIG += \ plugin \ qt HEADERS = \ crypto-handlers.h \ crypto-manager.h \ cryptsetup-plugin.h \ debug.h \ misc.h INCLUDEPATH += \ $${TOP_SRC_DIR}/lib/signond SOURCES += \ crypto-handlers.cpp \ crypto-manager.cpp \ cryptsetup-plugin.cpp \ misc.cpp QT += core QT -= gui QMAKE_CXXFLAGS += \ -fvisibility=hidden DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII DEFINES += \ SIGNON_TRACE LIBS += \ -lcryptsetup include( $${TOP_SRC_DIR}/common-installs-config.pri ) target.path = $${INSTALL_LIBDIR}/signon/extensions INSTALLS += target signond-nicolasfella/src/extensions/cryptsetup/debug.h0000664000175000017500000000207314615454535023530 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_DEBUG_H #define SIGNON_DEBUG_H #include #ifndef TRACE #define TRACE() qDebug() << __FILE__ << __LINE__ << __func__ #endif #ifndef BLAME #define BLAME() qCritical() << __FILE__ << __LINE__ << __func__ #endif #endif // SIGNON_DEBUG_H signond-nicolasfella/src/extensions/cryptsetup/misc.cpp0000664000175000017500000000373114615454535023732 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "debug.h" #include "misc.h" extern "C" { #include #include } #include bool setUserOwnership(const QString &filePath) { const char *userHomePath = QDir::homePath().toLatin1().data(); struct stat fileInfo; if (stat(userHomePath, &fileInfo) != 0) return false; QByteArray filePathArray = filePath.toLocal8Bit(); const char *filePathStr = filePathArray.constData(); if (chown(filePathStr, fileInfo.st_uid, fileInfo.st_gid) != 0) { BLAME() << "chown of" << filePathStr << "failed, errno:" << errno; return false; } return true; } bool setFilePermissions(const QString &filePath, const QFile::Permissions desiredPermissions, bool keepExisting) { if (!QFile::exists(filePath)) return false; QFile::Permissions newPermissions = desiredPermissions; QFile file(filePath); QFile::Permissions initialPermissions = file.permissions(); if (keepExisting) newPermissions |= initialPermissions; if (newPermissions != initialPermissions) return file.setPermissions(newPermissions); return true; } signond-nicolasfella/src/extensions/cryptsetup/misc.h0000664000175000017500000000245314615454535023377 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef CRYPTSETUP_MISC_H #define CRYPTSETUP_MISC_H #include /* Desired permissions for the files created by signond */ const QFile::Permissions signonFilePermissions = QFile::WriteUser | QFile::ReadUser; /* Sets user UID and GID for a file. */ bool setUserOwnership(const QString &filePath); bool setFilePermissions(const QString &filePath, const QFile::Permissions permissions, bool keepExisting = true); #endif // CRYPTSETUP_MISC_H signond-nicolasfella/src/extensions/extensions.pro0000664000175000017500000000011714615454535022765 0ustar coucoufcoucoufTEMPLATE = subdirs SUBDIRS = CONFIG(cryptsetup) { SUBDIRS += cryptsetup } signond-nicolasfella/src/plugins/0000775000175000017500000000000014615454535017327 5ustar coucoufcoucoufsignond-nicolasfella/src/plugins/example/0000775000175000017500000000000014615454535020762 5ustar coucoufcoucoufsignond-nicolasfella/src/plugins/example/example.pro0000664000175000017500000000055714615454535023146 0ustar coucoufcoucoufinclude( ../plugins.pri ) TARGET = exampleplugin HEADERS += exampleplugin.h \ exampledata.h SOURCES += exampleplugin.cpp headers.files = $$HEADERS INSTALLS += headers example.path = $${INSTALL_PREFIX}/share/doc/signon-plugins-dev/example example.files = exampleplugin.h \ exampleplugin.cpp \ exampleplugin.pro \ exampledata.h INSTALLS += example signond-nicolasfella/src/plugins/example/exampledata.h0000664000175000017500000000300014615454535023411 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef EXAMPLEDATA_H #define EXAMPLEDATA_H #include /*! * @class ExampleData * Data container to hold values for example authentication session. */ class ExampleData: public SignOn::SessionData { public: /*! * Declare property Example setter and getter */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Example); /*! * Declare property Params setter and getter */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Params); /*! * Declare property Tos setter and getter * Can be used to set Terms of Service message */ SIGNON_SESSION_DECLARE_PROPERTY(QString, Tos); }; #endif // EXAMPLEDATA_H signond-nicolasfella/src/plugins/example/exampleplugin.cpp0000664000175000017500000001073714615454535024350 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "exampleplugin.h" #include "exampledata.h" #include "SignOn/signonplugincommon.h" using namespace SignOn; namespace ExamplePluginNS { ExamplePlugin::ExamplePlugin(QObject *parent): AuthPluginInterface(parent) { TRACE(); m_showTos = false; } ExamplePlugin::~ExamplePlugin() { TRACE(); } QString ExamplePlugin::type() const { return QLatin1String("example"); } QStringList ExamplePlugin::mechanisms() const { QStringList res = QStringList(QLatin1String("default")); res << QLatin1String("example"); return res; } void ExamplePlugin::cancel() { } /* * example plugin is used for testing purposes only * */ void ExamplePlugin::process(const SignOn::SessionData &inData, const QString &mechanism ) { ExampleData response; ExampleData input = inData.data(); if (!mechanisms().contains(mechanism) ) { TRACE() << "invalid mechanism: " << mechanism; // next is commented to allow invalid machanism to be used /* emit error(PLUGIN_ERROR_MECHANISM_NOT_SUPPORTED); return; */ } TRACE() << "User: " << inData.UserName() ; TRACE() << "Example" << input.Example(); if (input.Params() == QLatin1String("Example")) { qDebug() << inData.UserName(); response.setExample(QLatin1String("authenticated")); emit result(response); return; } if (input.Params() == QLatin1String("error")) { emit error(Error::NotAuthorized); return; } if (input.Params() == QLatin1String("toserror")) { emit error(Error::TOSNotAccepted); return; } if (input.Params() == QLatin1String("store")) { ExampleData storeData; storeData.setExample(QLatin1String("store:") + input.Example()); emit store(storeData); } if (input.Params() == QLatin1String("url")) { SignOn::UiSessionData data; data.setOpenUrl(input.Example()); data.setNetworkProxy(inData.NetworkProxy()); emit userActionRequired(data); return; } if (input.Params() == QLatin1String("ui")) { SignOn::UiSessionData data; data.setQueryPassword(true); data.setQueryUserName(true); emit userActionRequired(data); return; } if (input.Params() == QLatin1String("captcha")) { SignOn::UiSessionData data; data.setCaptchaUrl(input.Example()); data.setNetworkProxy(inData.NetworkProxy()); emit userActionRequired(data); return; } if (!input.Tos().isEmpty()) { SignOn::UiSessionData data; //% "Click here to see TOS update" /* QString tos("Terms of service has changed. Click " "here " "! to see changes."); */ QString tos = input.Tos(); data.setQueryMessage(tos.arg(input.Example())); data.setOpenUrl(input.Example()); m_showTos = true; emit userActionRequired(data); return; } response.setExample(QLatin1String("authenticated")); TRACE() << "Emitting results"; emit store(response); emit result(response); return; } void ExamplePlugin::userActionFinished(const SignOn::UiSessionData &data) { Q_UNUSED(data); ExampleData response; TRACE(); if (m_showTos) { m_showTos = false; if (data.QueryErrorCode() != QUERY_ERROR_NONE) { emit error(Error::TOSNotAccepted); return; } } response.setExample(QLatin1String("signon-ui shown")); emit result(response); } SIGNON_DECL_AUTH_PLUGIN(ExamplePlugin) } //namespace ExamplePluginNS signond-nicolasfella/src/plugins/example/exampleplugin.h0000664000175000017500000000334714615454535024014 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef EXAMPLEPLUGIN_H_ #define EXAMPLEPLUGIN_H_ #include #include "SignOn/sessiondata.h" #include "SignOn/uisessiondata.h" #include "SignOn/authpluginif.h" namespace ExamplePluginNS { /*! * @class ExamplePlugin * Example plugin for Sign-On. */ class ExamplePlugin: public AuthPluginInterface { Q_OBJECT Q_INTERFACES(AuthPluginInterface) public: ExamplePlugin(QObject *parent = 0); virtual ~ExamplePlugin(); public Q_SLOTS: QString type() const; QStringList mechanisms() const; void cancel(); void process(const SignOn::SessionData &inData, const QString &mechanism = 0); void userActionFinished(const SignOn::UiSessionData &data); // void refresh(const SignOn::UiSessionData &data); private: class Private; Private *d; // Owned. bool m_showTos; }; } //namespace ExamplePluginNS #endif /* EXAMPLEPLUGIN_H_ */ signond-nicolasfella/src/plugins/example/exampleplugin.pro0000664000175000017500000000065714615454535024366 0ustar coucoufcoucouf TEMPLATE = lib TARGET = exampleplugin DESTDIR = lib/signon QT += core CONFIG += plugin \ build_all \ warn_on \ link_pkgconfig HEADERS += exampleplugin.h \ exampledata.h SOURCES += exampleplugin.cpp INCLUDEPATH += . \ /usr/include/signon-qt \ /usr/include/signon-plugins QMAKE_CLEAN += libexample.so headers.files = $$HEADERS target.path = $${INSTALL_PREFIX}/lib/signon INSTALLS = target signond-nicolasfella/src/plugins/password/0000775000175000017500000000000014615454535021171 5ustar coucoufcoucoufsignond-nicolasfella/src/plugins/password/password.pro0000664000175000017500000000023714615454535023557 0ustar coucoufcoucoufTARGET = passwordplugin include( ../plugins.pri ) HEADERS += passwordplugin.h SOURCES += passwordplugin.cpp headers.files = $$HEADERS INSTALLS += headers signond-nicolasfella/src/plugins/password/passwordplugin.cpp0000664000175000017500000000555114615454535024764 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "passwordplugin.h" #include "SignOn/signonplugincommon.h" using namespace SignOn; namespace PasswordPluginNS { PasswordPlugin::PasswordPlugin(QObject *parent): AuthPluginInterface(parent) { TRACE(); } PasswordPlugin::~PasswordPlugin() { TRACE(); } QString PasswordPlugin::type() const { return QLatin1String("password"); } QStringList PasswordPlugin::mechanisms() const { QStringList res = QStringList(QLatin1String("password")); return res; } void PasswordPlugin::cancel() { emit error(Error(Error::SessionCanceled)); } /* * Password plugin is used for returning password * */ void PasswordPlugin::process(const SignOn::SessionData &inData, const QString &mechanism ) { TRACE(); Q_UNUSED(mechanism); SignOn::SessionData response; if (!inData.UserName().isEmpty()) response.setUserName(inData.UserName()); if (!inData.Secret().isEmpty()) { response.setSecret(inData.Secret()); emit result(response); return; } //we didn't receive password from signond, so ask from user SignOn::UiSessionData data; if (inData.UserName().isEmpty()) data.setQueryUserName(true); else data.setUserName(inData.UserName()); data.setQueryPassword(true); emit userActionRequired(data); return; } void PasswordPlugin::userActionFinished(const SignOn::UiSessionData &data) { TRACE(); if (data.QueryErrorCode() == QUERY_ERROR_NONE) { SignOn::SessionData response; response.setUserName(data.UserName()); response.setSecret(data.Secret()); emit result(response); return; } if (data.QueryErrorCode() == QUERY_ERROR_CANCELED) emit error(Error::SessionCanceled); else emit error(Error(Error::UserInteraction, QLatin1String("userActionFinished error: ") + QString::number(data.QueryErrorCode()))); return; } SIGNON_DECL_AUTH_PLUGIN(PasswordPlugin) } //namespace PasswordPluginNS signond-nicolasfella/src/plugins/password/passwordplugin.h0000664000175000017500000000346614615454535024434 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef PASSWORDPLUGIN_H_ #define PASSWORDPLUGIN_H_ #include #include "SignOn/sessiondata.h" #include "SignOn/uisessiondata.h" #include "SignOn/authpluginif.h" namespace PasswordPluginNS { /*! * @class PasswordPlugin * @brief Password plugin for Sign-On. * Sign-On plugin that returns plain text password. * If password is not given in parameters, user is requested to input password. */ class PasswordPlugin: public AuthPluginInterface { Q_OBJECT Q_INTERFACES(AuthPluginInterface) public: PasswordPlugin(QObject *parent = 0); virtual ~PasswordPlugin(); public Q_SLOTS: QString type() const; QStringList mechanisms() const; void cancel(); void process(const SignOn::SessionData &inData, const QString &mechanism = 0); void userActionFinished(const SignOn::UiSessionData &data); // void refresh(const SignOn::UiSessionData &data); }; } //namespace PasswordPluginNS #endif /* PASSWORDPLUGIN_H_ */ signond-nicolasfella/src/plugins/plugins.pri0000664000175000017500000000112014615454535021516 0ustar coucoufcoucoufinclude( ../../common-project-config.pri ) include( ../../common-vars.pri ) include( ../../common-installs-config.pri ) TEMPLATE = lib QT += core QT -= gui CONFIG += \ plugin \ build_all \ warn_on \ link_pkgconfig \ thread DEFINES += SIGNON_PLUGIN_TRACE INCLUDEPATH += . \ $$TOP_SRC_DIR/lib/plugins \ $$TOP_SRC_DIR/lib LIBS += -lsignon-plugins QMAKE_LIBDIR += \ $${TOP_BUILD_DIR}/lib/plugins headers.path = $${INSTALL_PREFIX}/include/signon-plugins pkgconfig.path = $${INSTALL_LIBDIR}/pkgconfig target.path = $${INSTALL_LIBDIR}/signon INSTALLS = target signond-nicolasfella/src/plugins/plugins.pro0000664000175000017500000000011314615454535021525 0ustar coucoufcoucoufTEMPLATE = subdirs SUBDIRS = password \ example \ test signond-nicolasfella/src/plugins/test/0000775000175000017500000000000014615454535020306 5ustar coucoufcoucoufsignond-nicolasfella/src/plugins/test/Captcha1.jpg0000664000175000017500000001554114615454535022442 0ustar coucoufcoucoufÿØÿàJFIFÿÛCÿÛCÿÀ2È"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?þb?Rà95§éøŸéÿתއÛ?‰éúV¤+Ó¿Aø´ògÇßüi³ñ.›ñoáO‰5 ù¼9¦‹+G¸Ö{ócaˆuø5‰%Ôtû¤}PI»é“ÎÐYAaßüý¥<+ñr8ôMA#ðÇí‘–÷÷2”‡Q{uo>ã@šræ5ÒO§MFÄ ÖêÞ'ÐñçäœöÇýzþUÿj¿ø+—ì­«þÕ_>øáßtÿ|Ô¼c£x¿â‡î|­OÇ_<ã _i¾ ðû[¯|Kâ_Å“:éÞ-!Ñ[ìVrÞÉo©[¥¼Ö Õv£â_ èiöúïˆ4=ãUmt¸5mZÃN›R»‘‚¥µ„W—ÉypÅ‚¬6ë,„’Euñ/n¼øþµ_ðT¿ÙGö¼ø­ã—ý¢üñâ÷ˆ¼g¤é:Eî§ðÅWºÆ‹âYYéð]ZÞü>Ò$M:Hî$·X¯o¼-sfšÝÝã\M¦]êwW6ú4]Û~ÓŸðp'ÆÙûÁßþx?ƾøaðÇÁ:]¸·Ðt?µø¿ÆIá=-îü[qá«Ë{Ä“Ì,®/Ò;YZD ékrÇîÒ!ÓÜçòÿV”#§¿SÓô¯åþ Mÿiß¼E¢~Ï¿¶½§‡~|Nºš×BðßÅ[w‡üa«¼ŸfMñ&‰4k‡üAqr’ÎHôû¹Ü'Ùm%Ê·ôÉñö‚øðƒûüUø¿ðßáÊxŠ'¹Ðäñ§Œt EªZEå‰/-%Õ¯­b’Êšžð0µ†K›X噿Ýdöø—ñè=ð:þ•§éøž!ý x'ÂÚGöøß{¬é¿¾2ü6ø¨ønÞ+¯ØøÅú/‰/<;ÌͺëöÚ]ÝÄÚ4ó2îŠ×SK[™ xnRo<Éí>¿ k-pº>·£êÍgtö7k¦êvWÍky̶—"ÖiL1Žd‚M’®>dÓB½;t‰ëZŽA÷Ïà:~µBÓñ?Óÿ¯\·Ä߈:'ÂO†ž?ø£âE¹}á׃þ*øÅñ7Àß ¼=¹]WÆþ'Ò<9m;¢™ /í;»y/²ÒÉ..el$q;²©Æø)ûQ~Î?´E¼×?~7ü2ø¥öbéuiàïèÚ¾«gå}÷½Ñ ºþ×´Œ`•šæÊ(œ1»b?Ï÷ö=øùð7þ ÿ$ñŸŠ¿àª¯ô_‡Áp~|Ô|S}áo‡6—³j²Zé –êÖk{{Ó4ï"[‰îLxƒR–yµ åDò›ëø,ìû?Á.ü9àoÛ_þ ÍñãQø-ñMñÆ¢k? ¼?ñßTƒX²Ô¤´Õ|?ce!Ô$°‚D ®éúŒ·š]Å„ùCîI?½ˆGN;þƒ§ëV§»´Ó­.u BêÚÆÆÊÞ[»ËÛÉâµ´´¶…Y®nnghá‚bV’Y¥uŽ4Vw` šüpÿ‚"ÁG5oø)'ìgñÆú]¦‘ñcáÞ´žø•œtíST·³YôïY!ÝäG¯Y£\Íi½šÚî;„â3 ?à¬?¶ÏÆïø(gíÝá¯ø"¿ìCâëè÷°Òÿio‹:eç“âÃCoøËÃvsÀâY4øz)#ñ¤‘Ë«ø™ntãòlL×`³:Ïü«þ £|yÒgÛOÚFñ7‰u-r \x£ÃPI«|?Óµ¹®’É,fñté—F;§0ÝÝX½Å³#ríòÚWŽhâš'Y"–5š)ƒ$‘È¡‘Ñ”ÈèC+C85þlßðYïø"ŸÀßø'Ž›ûøCöeñ_¼wñŸã‡Ä<uÿ Uþ}âMwÄVÇB0ëš}†‹¦é6¶ztºÖ¨¶ÖpY´–Q‹h.nïn<ËÉÿ¤OÁ{üûþÜ ?àš¿goøj=/QøWð¶çã¾­ãm]óKñƒ¤i¾ø‡¶-q&ƒ%ìÖ±êí6ªoà ªOs ¥Ö”Ö Ó\+Ó·Aøžµ©éõÏåÓ?ó¯Âïø*÷üOÆŸ±Ç?fïÙƒö[ð‡ñ“ö»ý¨¼cm£xKÂÚ½ÕÇöƒü)=Äoü%ÚôZzÉu8¹Ô¯`þεÌ6ïc§ë—70ÇmÏûIðæÇÆZw‚€gõ¢¥„p;ñúžúÔPáÜC§nAþMiÂ:lþ'§éTb^Ý8ñ?ýzÓˆtíÏè?É  ÚÝÑÓô nü#R»¸û-”Óçÿð¯á³þ!ðGÁ_´üöŠøÉñN‡Äß5ŸüIð½üiqfž4ñoµÛkM€‰/´\ÜÞéŽÙ_¼Wj<è"eþÄh¯ö tëC _øÄ¾?е½?H´±‘cKi¯:E“ܯ—%ÅÇÚ§¾˜[ÛÙÆóM%›[“ŸÉüÎÿÁí>|&ýµÿk{Ù·Äþ(øåâí_F¿ƒÅ µý‡·~‹Ãþ9»MZóOñ®½%¶“â¸m5½B}4ZǤi>O‘p’] i¤ù·þ ­û^|_ýš઒k?5Â4Í7à×Âý7Ä^ ÕZ{Ÿ ø®ÂHu-`ÛjÚrK—w ê· a¬XÉmªéÏ4Ëouök›ËkŸèÿàÏÆ‹³Ïƒ¾jž<Ð.¼OðGâg†t/é‰m2Þx—JƒV¹Ót­Bu ¿µK™Åׇµ1kg©˜'»Ó&´Y.¯òþ ‰ÿyý§?ࢵæ§ñÓš{ü3°¼ðWƒ¼7y¡xŠÊÃXx¦ðöžld¼´×­¼A¥è7Éq„+mâM ÓÈý xKÁ_´mßÁ‡ßµ‡Þð~“¤øgÂ^ ñŽõ/èÞ)Ô­ôÍ N¶¶¾×to ZÂÖ¶ZÌb“i'ûSQ—L¼’ `¸Šx“U²ÿ>oø+WÀM#à×íS∟ ¬|Qgà‰Zî¹ã½>ú ßéðµö¡â^-'CѼF˜µŸU“M±¶Ö¯´Â`¼Ò¤Ô!¥ŽxÖßÓÿoßÚ#Å¿´§üçöñwo%Ôõß jß>¶©q+ÏwukáØôûHMÍÄŒòÍ!†(w4ŽÌØËrM{güöÝøÇû'þÝß´7Àý2 |Kø) ø‚ÏF‹á¿Ä}ÇR³:Dš6ç$:­„:‚OK‰â¿þÓÑ~Õ4×+¢æyÚñwü1çíQûü Õ|_r߱߅5‹ž>Óüm¤Ak«x7Fø™&—guâKkï'I´Ó ðÖ­böú¥©‘¼iÍ´Ñ}ªÉ¥ ~ó¿üÁŸ·'ÇcãìÓûkÀñJÑ­¾+ü[iî¬WÁ^ ÒîL²¨Ô­¸·“Pw0Å £¥åÉf†‹sJŽý¬>þØ¿ðD?ÛOÀ×QüsÔ5ÿ_hú7´ˆ¾Ô5›K?øtjo«¢ëšf¯wy<±EyÕ…íô·–íæ íäËe¡Oø7ŸàæûxÏãÒøÿâçÃ/x#âîáiþüDðî¬Í ëcJ¾ž;‹{û¹c“MÑîLr™Õ“XÔ4™PV’áZø§þÞÓã—ö‰ý‘|[g4z_ˆ~ øÊÊÂúÖXî-.†ã+K§{{ˆYáš?/]·pñ»)Yƒ†€j~ÞðQ¯ø,7íû/¿í[ð¿Ã×ìÍûéè:CxƒÃÚ”:W¼Wu¨[GmqâK›‰cMR=óSûDÍ¥˜¢‚! «’í%}/ÿæÿ‚ˆüJø?ÿ›$øËu«þÔ?jߎ>$øû1|*ñ~µ6¡âýb/'ú¤þ"¿¸k‹Øü%¢_ߥö³pÀ4‰[Å,RÜ<ñ~ŒÁV4KoÿÁ$¾ðM•­¾ÀO¾7ÚTÁg’<= êš„© º¬ikÉ'˜… ¿{·95ü[xSÇ¿¾ þΰíUàKy5 |ø¿ñ›M²á–÷FмhÞ.³ñdvÚÌQå-_^Òu™>Ï,†'–;vòŸt@¨õ5¯Áªÿ |kðçÄšŸÅcÿ¶7ˆ…ÿ5½[ÂÖ:~‰ð‹HñF¬N¡‚<7áK({h’ºé««É}>§¨Ü$𛵍”[/ó‡ðoö6øuà_Û’ëö(ÿ‚®ø›â·Â KW±Ò<%ñFÛ^¾¼Ò#ÔgÛxZKù5ˆõ+ø¡þÍm¹kK¥‰XIueK-·ôð#þêø_umc§þг¿Š´m@ù^k¾Ô,ï´èÜmŽKÏì½Fqw(lf…g¶ÚåÄ T¯Ì¯ø/ïü/ö(ÿ‚…øOàßÄ€>rü\ð&£=–±«Ýiaª^xOR‰ÛK»ºØ¾|º^¡º‚%–FµIeW’›À?¹ïø'×ì ð'þ ñðH|'øu Í\»ÄšÏˆõk¸ooüIªËnë§-ź¬ ‘0KA(¶Â<;±goóÖý¯|1ûoÿÁ?à¨ß¿h 7FÔ¬õÿüMø…âï†þ:Ô,&¿Ðþ!è~<Õ¯u]f×NœdÝL°ê“X_ÚBÒMeÁ¯œˆßÒ¯üCþ ú×üãâÿŠ>6Ïâ/~Ãþ·°Õ5[¹w]x““ØÜÉàÑ<ÌKµ[#£Írä³c’F-’~|ÿ‚!\kðY¯ÛköŒý¿ÿl›ÛˆúOìÿýà¯õö]WÀÿÇ ¬]Zêzo…/¼í3~Ÿ£i· ý¥öSsuâ ©u™^[{1å÷ìÿ­Ñ~5ÿÁQþ~ÔŸðR ͯZø/HÓ¾üÓô+ƒÂõ­Nò;i|t|=yÍæ­=ãCs©_4‹4F'ˆ¨³†5ýeÿƒ¯bÇñçÂðQ¿„QÇ{uðûû#¿5-7kIsàýzQ«øÅ1´J^TÓu7kYd-¶/¢“#æÏÿK~β|û:i¿¾øÁŸµÄ_‰¶ºn•§øK±Òõ½cÃ"‚âóTÓ´ÕF’/ím㶺{pÒÜœs»Ñÿiø­ñ[â/Àߨ7þÏð¡’ëã_Çß|-OŒ“ÊÒOyá éš]‚ï¢Evˆ›˜îä\l¼FÍ‹sŸðm7¼aûw|tø£ÿ4ý¨|Skñ#âoÂýÃÿ¾Zê3Ãw/ƒ-tßCcwªÚiÅŸìK¦Éq½ÃIJµÅýÍäoæÈ$ÛŒC§^¹ÿÃ_æ3ÿ®ý¨¾"Á ?à¨eÚEî¢ø[âŸÛü<ø‰qÜÛévÒË2ÂñCL‚åQ§Ó&µ¸ŠIcÞöWn þš¾ÖôŸhÚWˆt BÛUÑu½>ÓRÒu+9R{Kë ØR{k˜&Œ²I±::²’0}h¢„tã·êz~•©öëÈ€ÿëUGN;þƒ§ëZqøýOù4zÓñ?Óÿ¯Zp¯NÝâzÕ—·^@üÿZ´á?ý?úô~!ÓëŸË¦çEKôü·=h øGOÄÿOþ½iĽºpâúõFéß üZÓ„tüOôÿëÐÏþ.ø /Œþ7ø+⾡â$Ñü+immÿ¼ºl‚Búwö¥åÄŠÞ0ðWí ñâ~£ãN÷ÅzG‡nôxOÂþÑ-|;©êѦ›.•ªÜß:XMx äbÞÂìåÿfŽœwýOÖ´¡8íúžŸ¥7ðGŸø!çÄ_ØWPøãí/ã…_<ñKC𥯇<3áƒâµ¼ðƹ¡^êÒjºášþÇK‹L¼Ômnì¬íï´MJkÙ¬­ö]5¦æµßðXø'ß…ôÿ|4Õ¼=û'übý®þǪxÆßÅZOð¾(ø›ð)/­tK«]ÀšV•6“ã [Fñ–WøŠßK¾ýľÑ®5Éu8žÚ8?§H—ñè=ð:þ•§éøŸéÿ× ç÷à¼þ8ý¤?à”/ý™|%ð[Å~,øa«þÏ_fŸ xÛX¿ƒDø…á›o]øCAŸÆŸ üWm¤xŠóÄ ½¼Ó¯n.tèmÓQm:²XH\]~sÿÁ?d/~Èý¥~Á@|áþËÿ&ðGˆ¼w¨ø7ÇÞ$ÐtøZOi^ ™´ÝGáõΙ6½a«h±ÞÜ·˜–w^DieþË!@3€±ˆæb’Or¨É=Ƭ#}óøŸ­:ž2ÿ‚-ÿÁ¿hËf¶ð´>ð]ÕÉYmàð/ļ#ª%܃]dê3Úê3K<æÜGqlñI)Á‰AÛ_–?´Gü1{&£.¯û-þÐVºŸ‡î‰žËDñý”v—V–ê ´¬i¦öMæŠÒî+{`dòÖæFk¤þÏ|GðWáƒü2ð.¿,›™®õ/ èóß©l‚ÑêdÑ3g%¢¸F9$“^Vb¿‚ÖrKsàY>"|&¾™·½ïÃ/‰>.ðó¬ÄçÍŠÒçQÕ4ÈYN6¤V ÆLD’Hâ×üƒþ//ìßûþÕŸ³ÆÏXkž"ýª¼©xKÄz¶ƒ‹ÖâÊHtc§,§ÍšMáþԳ͓5Ü·’*ÇÑCó³ð/þ ÿóÿ‚n~о5ð¿ìá[Zxµß÷=ð­æ…«|2ñ¿‡¡»c§êºœwóºY\ÙFÍpVîÚÛVÒÖIg¶&ÏýëÇð#öðÞáý¬|Wqko¥|Tð7…<ç„ ªÝø‚Ðu„c†V¸‰YØ4lv²Ü}KöèðôÖvÿðŒ~Îÿí$˜£ê:V±ãO_ÁÈ—Q³ÕޝhI6…“K’ó£Ù"ÿ¤Åßø'/ü³âvƒñºÃößÿ‚¨|]ƒö¬ý©à– gÁÚRéúv›¦'‡t;ØCioz`†úOØOÿÁ4?f~ÚÞ2ý¿ Ÿ|SûDøËH»Ð޳ãK¬ø{Âú]ÔuŒ>ðÚÚZiº:N—§7L’ÝôCªkW•æ¥}~. îbñ‡í«Ð|ø(z~-kc§ÓÂGµhGã/Ûh—àÁ#Ôóñs\ßô(JóïÚ;þ Oû~׿<1û@þÑ|9ñ3â?…ÿT¼Õ¬lnôý:þ}GK}jËE¾ÓN±q¥ÜÜN,šúyaIöiàžH×ôÃ>Ñ|)¡hþðÞ™i£hi¤èÚMŒB=;M°-l¬íb ¼Çk’B¨É'šù?þÛã§ÀòWuÁü¼ rjô~4ý¸øÛð3àiè9øÁ®ŽŸ÷'ÝhíXW§nƒñ=kRÈ>ùüOÖ¾&Æ¿·@Æß_Éäóñ‹^ßô&ÿZ½¿nÑ¿þúsñ^êîMÿûz!Ó¿©ÿ&´á^ŸP9ô?­|Çð§Ä¿µ­âkñsáoÂïøDé÷rcÂ?5_êãSŒÃö+_ìËÏiý–pÓ™î>Õ¾"ˆ7ÞJýCàwãõ<ÿõ¨ô#§â§ÿ^Š–éõŸ@3úÑ@‡QãýkN.Ÿ‚ÑEjCÔ}Oò­(z¡þtQ@‘uüWùšÒ‡¨úŸåE¥Aô?ε"ëø¯ó4Q@qãýkN.Ÿ‚ÿ#E©Qõ?Ê´¡è>‡ùÑEiEÓðZÔ‡¨úŸåE¥Aô?ε"ëø¯ó4Q@qãýkRßð(  (»¼?¥iEü?õ¢ŠÓ‹§à¿ÈÖ¤=GÔÿ*(  (z¡þu«o÷‡ô¢ŠÓ‡·Ðÿ:(¢€?ÿÙsignond-nicolasfella/src/plugins/test/Captcha2.jpg0000664000175000017500000002720014615454535022436 0ustar coucoufcoucoufÿØÿàJFIFddÿìDuckyÿîAdobedÀÿÛ„   #%'%#//33//@@@@@@@@@@@@@@@&&0##0+.'''.+550055@@?@@@@@@@@@@@@ÿÀã7"ÿĦ !1AQ"aq±2‘¡ÁáBRbr’#3SÑ‚¢²cs³45ðCÃ$t„EñâD6ƒu1!AQ"2aq‘ð¡ÁBÑb#ÿÚ ?ú" """ """ """ """ ""/…ÁKʼnxX™B¸£b-\`¼ãñ¦[‘iããñ¦[‘iããñ¦[‘iããñ¦[‘iããñ¦[‘iããñ¦[‘iããñ¦[‘iããñ¦[‘iããñ¦[‘iããñ¦[‘iãè”'2Ú½ZÃê³LQx½^ Å΢æ’z-³Š2áÄUuõë–mnu×…ku×…p:CUy^‰êŒy;ÍÑë^w£Ö¸5ÔV¾Ü2ïïG­;Ñë\Šj)öá—z=iÞZàÔSQO· »ûÑëNôz×¢šŠ}¸eßÞZw£Ö¸5ÔSíÃ.þôzÓ½µqw´fIÞÑÒO™V²\×,•ŠÀhnî!ôˆ.{ß^œþÝ×Yµát›)oÛLÈþs€ó­1gñÒ1ÝFNêçT‹,C"á=ËŒly©{ê\|AG_ÛGitøb—ŠÖk-·ÚO/ k~-Íe鞯©wªô¯{ÑëUNV–íÖnã8º i­êsQ]ôÖm¬Û˥ÿ½´ïG­pj)¨­}¸™w÷£Öèõ® Ez )öá—{n [ã•Å R0¹oˆ³-Ñ’º°c(¶¼ûVãÔDYQiŠêÞg9‘<9ÍÞ¹Ö·+eœÌñzŠ R6¡GÜŽJUÏ4u ¦›b¥ˆYBµ!q *£ÞøšâÒö‚Ý⢡zõÚXå`‹D·ÖpŠË;ãp¯°£ny£Dz¦wÉÉWmôפY­¼DÊ*¬œß9¨ŠÝ­ê.q>Õ‘ÌùgŸ«cO€0•Îÿ'×ñ·ôkíì¸"¬GÍw1¸ «jšT`©«,µ•ðöÎö;c–õöé·Izü/Fn›Ncµpf/Ýadé˜*óÙo€ž•­¬’ÛÙ$ÍæâîÚÕšç0xNßaWïù³{,YÿÊÿqªÉ=íÀãIW<ísŽÁUcn3‰„\Ý;¼?à×h$|P¼ßwf|q¦³›]`»írw‚¶ÒµôÞ7`íU[ìf"Þ¯ æ‹@§È£¬eš¸Ÿ !ú†î®•Óïï®Ó]¦¸ÿªxK3-ý_DEãMZX^¯S¶ÄÚ•Á{’´°f»‡Ðô4mqò(YùÒVÔZ@SÞkíÏÙí×^–õø.ºÛÄ^í¢Ü¤#eùoÿ¸ÎF:6þ`%tEÏÜÁFÆñÐ\Ê/þÉk¬ÒÇÓ—ªƒkë.M@^Y=.ƾÁV|W3áò´e¼á³}Ô—y+¿È±•ÅK¢"¨ÑwsÝ£i×Wi¥iÐO‡©r~/ûÒÿµlË,ßž<ÎQ!'ø·ì¿KþÕï⿲ý/ûT`Y⟲ý/y{øŸìÿKÞQÁdH~%û?Ò÷—¿ˆþÏô½åÀ¡â³öýäïÿ#Û÷—YGg}ùß¼½ïŸ#Û÷—YG_{ùß¼½ï_'Û÷—(^„]çäûiÞ>O¶¹ÂÈ ßÇù>Úɲê R‹œ-‘zaB" """ /«TÒˆÚ\zl^¨Öe#sô®øäkÅAAš" ""(,¿8á±Ot/ÏrÃGChƒZ»ÑuVª™{ë9póÝôZÆ@£Z5ùÎS+%}A{‹œM­ÅÑšXÚ÷)ZŠ®¹fŠk•Ú[º¾"³¯Ø‹ädŒaÔ×m,A\E&>ì>?Gk£ØiC°´ÕME#e²3Ñp¨Z¯-[u fÀñµŽ=ßQØ«“ÆÚMÄì;‡ÇEÞÿé¦ÛNϪež/*KÄSÃUBç‹vÅ$³²÷T:›*:ÑÞÐBùW8å”s!ua·Qp=¥»¿Éa¬ë” $ï5YÁסa{ÎàVË;9.žhC"fÙ%vÆ´.áx#i³Ä0[$¸>›ü5ø!s×\õ¼{ù7oÁµ¶Ìpב“8ÿnjԜVc˜+iePƒ@iî®&6ÊÝÕ–·—'tmû0~S¾‘v]3[.Zaolݬ¶`¡?šYoc_ËüìÅ“¿_ë´LbïY˜…ââÝ 7a4«O‰VòðÃe‘slÞ@mÃ螥×q̱wL\\·oyñ/1ü¹wvá-Ñ1FMM}'-oo²MuùöœíÁ'Žmé> N_ÌÜ^—¥ï`ûQî©<„wöÎçMvµÃ ¬í,­ìâ@ÀÐ7ž“ã[×§Mo‡Ž÷ËâålÎgE.ó–¯mXéu±ñ³nªé4üå^÷PM7j¬\Ñ“.p±ˆöFÙ<} —±fòäM ú˜¶Ÿ è Ǿšßg‡¯õv›_ì–Àc#²¶7×"’¸TWà·ßPYœ“²E¼l¾ê—ælžÜ!4ûÊuu(œ&5×÷CWÙGÚyë§B׳·§NÜþi¯}öekËÙ˜›3Ç ´“BºG*dO¥#Œ•nkCZÑ@^®ÓøÞ¼uÍcîl«EÉò“õ× ä|ôRÖ ' 2J7=ÞàRh·¯§×¯Y¯î—}¯qqer-ÇÚºSµçcÖWj©seÁ}Û ²ÁR<%=Ûøil爚Lí„-ÍÌ×R™fqsZ³òÇ)²ý¢îú¼èF6jñªÞ>ØÝ^Ãn?¼xEöfA "`£Xļ:ÌçkÕßkŽ‘å–hÐ ¶”éÒ*º_eg'§nñ´- P,’²ˆ¼ål ãH’ÑqþñƒK½¨¼ËÊ3á»´{¥µ'ÒÜøÏ†žuõÏ{gõ³ínª)Â¥‹*ÉÜß$Ïf3$ýO; Çi= r¼ª›½^b„’Þy¡sshC¶ƒQ½Zac£‰Œsµ¹ ãÓN”™.;8òÿË7ç3•ë™ïì/%¶–&J굦Šÿ—þY¿ï¼ÃÚ?ZÍÙMûŠëUŒeöžÓ¦HÑ«föôVV9¯h{MZà>·íÒK~ºÆu½¯1’"ÅÎ iqÜÑSä\ÚWyϘ.ÀÛÀáÞîkzØÞ—/–WSªã¼Ô•%Ì992™I®{ –F:ZhœN.ç-zÛKqÚv×;¡­ÉY½[“¦K’ö6·àŽ“ÖV.Út3°Î¡ÓãWxý]ÛÄ®.žóÒÖ´쮆òæ.ÓЀ9Ãá;i]4õm·|3w‘G³ŽúNÍœD“ðÃj~’–¶åk¹Ý®ö]í vœ­!nÆ€Pؽ^¬ú­ÛûG;콺8l°öT1F ÇÃv×.äEÚk$ĘbÛyRù–6˜žÖæ·Ø©|Å‘7Wfª‡`ê'­cÝìðÓ=ïH֚棘ٯnƒGjI]çW:A†ÅìÞÆôïsŠŠå\x%×’ Ý–çZ9£!ÆœZ0ö"ô¾róéÿŸ®û/Õ·HÞß6Ó^Ó”<–îà¸ÕÒHï:¼b1í°´lÞ8U笪ÿ,c„ó›©Y£ó•¹oøÚt»Þo ìÛý`ˆµ\\Ám’g†4u¯M¸åͰÐI4yPW9ƒy|Ë #FêúÉGƒm‹Ëó ×…ÐÛ“¾ãÖïèå;]RÉrá±£K|kÏ}Þ{Í4ã=k¤ÓíV¦·` ‘̵üVJõ|‰•*—Íðp²•øíªŸÉ¿,Ÿ‰ê寕œ·V†£È¾¶ÆÐ/rÌâ Ý«Îâê(_b^]oFöä^¢*‚" "" ÇòÍùãÌåHæë~%‹&ãvßWlÇò¬ýàó9V²ðññÓ²•:uÍÚ¥Xùâê°ÈÝcå2Ú»Kœ(àEA×14YÛÈ"ž9H1ÁÄĹeµ‚s¼a¤ð²AÖ;%HÛóƒÇׯøàíiw? ‰º®6죅Ahӿĸn¹Cö9Ð9ñ8 ]CÛW«=öYŒ}óƒ-¦}+£s½‚»‚ù…Óñ¹æ Ö'Q㦛œ¯vœÁŠº!±Î÷l d’|jÊX• б çe¼/šMŒ`©ò"7…U/ÿwn$§v»ME}…'æ¬MïdÉÝäø“Q¿¥è¦LTØY€5Ú7,‚ Âô,Bô*3 l?h<¾e¤-°}£|¾dGZ" """ ""›‹vÊÒ[Ö›»¨,í¤º¹vˆbisÝ¿`ð ¨óÔXhõ¸ƒ+뤞¿ULLSeòÂâóëcŒ‡Ëª…¤ Ì¡è\ùœœù¬œ—Ddv˜chmhÖìéW[á8è£xáÀ:s³Ó;ÅFúnYå®"ÇaxÙZº›(»•wòÙ€Vî L²Q9{RÞ›¸Ñ¯wôqK,d’0±ãS]°‚µ¦þ;Kû¥™Ž|}×y‚®?XÝèñxWRi“yCµ£a4ô˜z«ýª§AÍ5h#q ^Ý$¹ŸNÝbksùÇ{ccžó¥­¸ž€FöF[È£-ÄZI¦:z2<|/R\É6Vþ>ZÇ8Õæ·Ò€Á½µV ŠòêéŽW5½@¯+utê r¸ô ”ŸÉ“Y&½dÁ}}sjÑÍ6ÐÕ–£ŠÿðB­]ßÝ^É®w—u7 .ë>[È\PÈÞ :Ý¿ØS¶¸Ln5œiÈs›ð߻ȥ×Ýíú¾]c:kÇZ„ÅrõÅÙÎ Px}#äVëKh-£@ÐÖ·«ÝUÜŸ3°Ø ›¸„SØ g—™'áñºRKÞK‰=5]=_o[uÓæ¸ë³;ùY›ÓðMÛ2¤*ï?X½è48øÊµZ³rÏ/‹fO-£·¸ÏœÅÏÝsÑtèøü: ™3}&G‘}¯tË»(nµ¯`>Z/ŠÜÛÉm<–òŠI‹\6ìRJ·É³ê³š~ÍõÀà¬aišù÷0Û l¬Í²ó¬~vÕǘÞ×·{H#Æ›-€’ = XO‹j«¬Õ¨ã®EÕ”7á´ãY_Àn¬§·äcš+º¤(>M»âØ>ÜžÔ.Ùâ*Æ™|˜‚ xØ·ØØÜ_ÏÝí€t¤Ö’i´ïVŒ¯'Kqs-Õ¤­R^b}Ghí !DG‹Ìá¯!ºu³È‰ÁÅÑöÛ@v‚[Z,ᬳÅóK7wŸT°Æt>¬¦Ã¦»¨¯¶ö¹ vÜ[<=„ €v´‘].SùÊÆ'rÖô1Îy&—yB‰Àå¥Åß1úËmÞà.¼Wi§XW„Æ_Q еÇ#$cdÁÌxk†ÐAÚY…Q˜[`ûVù|ËH[mþÕ¾_2¨íDDD@DDD@_=õŸãKø5¹ú¸ˆuÃÚíŽwÝ>/\óyFb1“ß9ºÌc°Íڞ㥣Ù_ži.&|ó8¾I\\÷ä“R¥­k^CÄ ÌŸ~™µ‚ÊŽÜeøÆõuÊÌ×vB‡ÀŒÃÅAH8“TQÚðO‹rÜ]$Îë%!yoÇg ÆßD(HÝm‹µ}õëøpÆ*ã¼øk†z¶½¾ŽÃk$ÒJðÖÈú5´éu7ì‹Z/i·zõTqd­;ÄZØ>¶=£f׋±@_óñXçC×u'fÕ t¸íö+±Yo.ಶ’êáÚb‰¥Î>%DÇE>Rôçæ‡o¬‹HéV‚ßivõß-o®þz³f/—îÏ ‚æûa$‘p­¦¸:¤ž^Ô†½4R£•sm?‰f%Û½-V;K–ÜÀ$–çÔpÞ·®7\\^Íç*Ë92É4Òt=ï'o‰k±Æã,nK.-G¢íM-?mU©päìøìâ°+(>k¹uõm>¾¿µgló9ŽdÀÛ^â%†›‘qém%Èù43`îÉÔÚ˜ú ÷›zÒÑm1Ûº2wSâþELæ[Yy˜"ÉÚ1Hí{7|¦•Ï}n›~]×[6‹U¤®±»s%ØßFMþGý¶),¬ãsíq¸Wȸ§t9²6çQÒ §Åñx*·âîD°›gís¥zYïUuöO=g²sÆÌΗ³äV·sã¯8ðveŒ$ôt/¦òD›ÙžKŸ#Ü\㼑±P9£ë Äì¥÷´õêÛ±^ù ÀàÚÖîcˆ>3Ú÷WžréxXdÜ£nºT”›”m×JïêåÏdd›Ö 97¬¶pæ""#Eí°º¶’ð§P.­¥µ™ÐÊ(æšx×Ñ—GkoÖ7L áq÷z|ægÕ4ßÇž¼G0Éd3ƒ$=mSíËaîÛÚ{Mw‡ŠyÔ ×+^ÄI„‰[ÑÐW±9:¸ÍýÚO¯”ü[ºé·Yp¶¸à›Ú.‡ÈAZäÎa­…A#pk}ÕV¬4¹o‹—²’õZAé%_½ìÿ_^?Dð×¾É ®my«mbÓòœ¡n/o/_Y^éw4~E9kÊ$™€L÷Ôå–ÆÒœ8ÁwÆvÒŸoÝ¿×|gõØòÓ^&UŒo-Ý]ùþ¦/¤|ŠïclØbd,ôXE“!=KºÞ -ÍtõΜüY¶ízº-£  µ¢k‰” jóísZŠw9ò©¼ÉX·ëØ>¶0= :G…|þ 糸l±Ñƒ¸‚ÜUc˜¹*×&]shDg~ÎÃ…bÆåø²å¾pµÉÄØ.Ü!¼h¡©ì¿Â”EFÑÖ¾/Ãä±s\Äæv"»1üßœ°hcg2±»›'hÕµLüK¯ÁõÔ_8ÖNI­íÛD÷uÔí-w>±2Ó4ˆbŽzGkήbxÔç=æ%°Ž­&1Ü8ê!§m<*¹‡æŒü×ð[—=²<Ò+Uuwu9šáî–WçiW>Få©Y(Ê^0²ŸbÇoñ©Í^"Ù™¯tewëªå ¦s_ʳ÷ƒõ\¡UH¨ótA·¬’ž›|ÊZù¾:à ½D…TY­NNŸEô°“²Flš«_=åù¸9{wVÎÐ8i_A ĨŽj·ãbœà;Qï'J¢/¥ßÃdzš#ðØBù«kˆ;Á¢U‰îOºádL$öfm)á ôÌ1“›{ø%4¼{{ÓXàæ‡ ÄT$JçÊ_þc%Öe››á*›?8eäqá¹±7mmwøJ·æmÖ.æµÅ„´|¦í æiHë¼ÊßÞ´2ægHÀjwWĹŽÚÞë)cqÝÖzϘ±íÇå$†6é…Ô|c¢Žêñj䬑¹°uœŽ¬–¦Œ©Úc;½ÊÊ˰ŽÉÃ=iމ~k¶õk´-D¬ÂÛoöÍòù–·[}³|¾eQ܈ˆ‚" ""ñz¹òl²²žíôÓn}N‘ZyP|ÿÖ`]^³¬v¦²õ÷®b,ûíüP¸U•Õ'ÍnÒ<«šây.'’y\_$®.sŽÒI*S–²VØëâû¡õR7Ip#mV;·Ä^ ³’R(6){\s"œ«W<ÿжn‹púls» ¯—j¯å¹Û/“ˆÀ m¡w¤Ø«SùÇjÖbb»yë˜#»•¸Ë'‡ÛBk3›´:Nªü•Ûêï á¯13h c·¯é;ÜPœ±Ê·9©„Ó‹/N‡kX¾§1[ÄÈahdQ€Ö4lŸô˜l^/W6B+©¬åŠÍâ9ÞÒÖ=ÛšOJ¬ª™Û‰¹0Ì“¿ÊÀíW’·uFÂ<ŠÖ,`e²‰¡‘5ºXE7eGrÖa­_Åp’òwjš^¿šI™sÝoÁi;¬n»N™6unpé÷”âŽËZ™.éF(á·kkî/qW|Xø=¸Çgfö ivöO=g²sÆÌN—²A‘KCûÜF€‘¨ š]ñ…?µW>JÊ>aÅ:Ñîí¦’)·¬xúTñÀµÂ ì î!A͸ëèV­'q-rí®=šø_«_¦³~[˜Ý˘Y0Ö"ÚIÌÄšw7ÀTÈà¹ã±ÇH®–uTSzé‚xçŒI«O²Q[9v×2tÏJ×KÕMõ…‰ãZ3!íÂt¿æÉêæì>Â{Zí‰ú¾—ý®òÚ;»i-äd->UBå¶Ëƒæy1ólŽjµ•Ük¸¬w^Ø}MÊ2èïRRnQwGzïêå‘ïÞ°Y?zÅ{#˜ˆ”DdJÈDS*Ö”[¸%z!*yC !«6ÆJèe¹= ¦;_ÆÞÉG %tÇmà]Œ¶¡od@.;{Zš¹£¶¡t² Ðд\®öµ‡€Qd¼^¬(ˆˆ0’(åadiÞª…»äÜ É.îâ'å›ê ¨IêããVO#| ò?WÁö“HáàØ®¦"æ¡l9K `àøàxÜçíS (ܨª#³ʳ÷ƒõ\¡ÞoùF~ð~«”"‹œ{òœÈkÁ¨.Ü«oå\«}±þ'çWEê˜\¨ÑáröÓÇ)¶qá¸;³ÚÜkЯm5¯õRÖDTÖ¾q”‡ƒž>€òGˆí_F Šë Œ¼y’x{·¸U¤û RWÏ Ôo éX‹ŽñŽ‚ZÖ­ØØ¢¥äücþÍÒEâ:¿YJbì?µÜC#ZIkˆ¡¡HZîð/™å¬Í–B{zQ­qÑóIؾ–4`ߺ¶n«˜… ÃoåJE2Òáö·Q\3Ó‰áãÈU§œaŠêÊÛ'o¢]ò]´{j¤æ9Ž,x-sM;+{o/]oÜDŽt ˆ·ŠøŠæ_Lå›þý‰…î5’!ÓÆÍƒÙWÍ ÐïÕ§‘o .¦³qìÊÝl)»ý¥ax^[í¾Ù¾_2ç }¯Û·Ëæ+L¤DDD@P<ë’råÓc‘¡Ä¦¸§–/c$acÚÇ 9§h!ÂVÈmçÚaÒ;© •õ“Éü¼eâ›F—WU t×ݾÇEnÀ-ãlq·sÈp×’‡Žäܵù ‡áHvýµ[1^¯qö®l·Ò¹Ý¤~Æò·Z\dJÅo0•€…d‰mgQÃc‰¡‘´Q­h ÀkÅê¨""" (+ˆ¤Ç݇Çèít{ (vš©Õ¢òÛ¼Àc­½„î.ž­üo_§n•6™Œá•“DÙYè»uwõ-Š;ã˜Ú¼P:¦”ÚÚù˜SÙ§ŽØýgäK˜-76í¸…Ñ;ev‡o¡+r,ËeÌì¨;K‰,n] ¦‘Ö'oC‡öܧ™mmæs_+œÝÄû½kr׳y¶,˜½ÒL"³™‰±16fY¾éŸ °¤*¶O'ŽÏFËû"aÉZî¶9Íh:ÕñÍkÚZðÓ¼¡Tsü’É‹¯1Gƒ8©1Îñ.u©†Ø²ÒÜ_Ø\q)Ôe†.†½‚§Î¤®ºWÍ›sÇ_CØs8WIðžÒúAsn!dÌÚÐížU×Óz³¼p8m^ºxË|vÞë»Éðâ›`%H¶×À¶¶Ø…Îû—Å÷t6×À» h`\¶öÖ¦®j:–BÔu.Ý!4…Ÿ¹Wf[€·60Ê"ÍÚÓBõz‹*""" """ """ ŽÍÿ(ÏÞÕrƒS™ÏåûÁú®Pj,z½X¯Pd½ ê Âô,W¡AdddA`ACŽÈö§Ž’}ã{.\–<¥´¸lúŸ)a«C©JùÐY2¨dù6éóË=“Øæ=Å͈öH¯Ew(ëK ®! ÔÖï ã[€«t‡´Ђô&,šààÓPvƒà]Ÿnß/˜®p·Ú}»<¾bˆ’DEPDDD@DDªx„Œ ­«Ä«ËgC!Ù±oÇ]–81Çb“¾¶°ìÚ«ïk¡“ªŠ*ÔÇ …’Ç]‡´4ªETzˆˆˆ€ˆˆ1Æd çauHñ¬‘Vk—ìsÎÚJ= FðW&a ¬îˆ’(ÏÔÉZ’<*}(¬¸¹‚ÜUml@-Ô­ÚÔÃÀ½ÒH³•x‹Ô@DDD@DDD@DDD@DDD@DDÙÏåûÁú®PJÖøãi‘¡àm£€"¾U‡t´ûˆþƒ".U…ê³wKO¸è7ò'tµû˜þƒ"˜2­/U“ºZýÌA¿‘;¥¯ÜÇôGäLWõX»­¯ÜÇôGä^÷[o¹gÑ‘0e] ¬ÖÛîYôGäNím÷Lú#ò!”Y;Ý­þéŸD'v·û¦}†Pad×w·û¦}½îð}Ó>ˆTCèS>íŸD'»oÑ"BßgüÃ<¾b»øýÛ~ˆ^ˆ£i«XÐzÀš" """ """ ðŠŠ(œŽ®ÛÕ.±sC…  ¥lÛˆ }¾ˆX¶4ÔšQgœy’ûÜûœqIÞ8ºø¡Î§‡Jh{~2âÂó75_ßZ²çe9× ‚`ÝsËhz×7¬ÿøÏ÷à«nú7ý,Ãj׳½AS-a‰¶ï7ÒpÙZ4R®sºšÑ½EcùãrÛVºH$‘Úc345®'u \êWÃD0±"ÅÎk^òÖ‚\âhÉ*µ?¬_ŠcxÓ4c`ÑúNiöYÑrã²Vy;VÝÙH%…Æ•¡8okÜW ÜÙËð]>ÎkÀÉãqcÚæH\7ÕÚ4ûh&WlùëyzÛ6:F:GÇ, Î;…u+á c!‘³Æ[«Ù8P_¥ÎÚíÛ CŒG:bò÷̱¶ŠvK q‘¬ ìGÑ‘ÇÚVòRÈZcsÝÞÉÂxsô¹Ô.ic+ë÷V÷6Ì»…áÖò4HÉ Z4‘Zö¨G•IVÌ7"¬Ïë—áœÂ,À ±°ö|ç4Ÿ SÖW¶·öÌ»´K‚­pöÁh!T©ƒç[üžr,d°DȤt€½ºµ}[ñ½Ôø*æ¾KÊ÷ZóL7øsÞ퀪÷ŽçL.JüX@dl4‰ò45’ôi©>È J¶'Ñbç5/y kA.q4 ä•ZŸÖ/Å1‰¼iš ±°hý'4ûJ¢Î‹—’³ÉÚ¶îÊA,.4­!Ã{\âºFsîFÇëŒe¿zºhh|’v1U6çŸyžÎAÝŒ6ò¨2X¦c‹I¥héÍ‹è«æž²®Aþ•ŸÄ•J±ô´DUD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDDACõŸÿþãümÀÿCÆÿ¥ƒømU/YÿñŸî?ÁVÜôEiæ\ó­9hdm+—Œ[—P9œfë­6öƒkåT«%½Ç+äs—%Ò\±úb««5=ÝdêéV‘7êÆGò1“Øi…Àx\$õB¯ßÁÏ:Im0Õ×â9R*×ÊáQà*{Õ‡üŸûñ”,ÿûàÿì™üf©ÚëÎuÅÚbs-ŠÉœ(d…’µ€“¤ês 5mø+èo²µÏamÙ{WE1UœÒñ-å\m®S5Ø&µåÁ§I«Z\6«Ï79¸ŽT6v„±ŽÑjÂMHfò+ákHUCÿÙmþd¿¨åkõŸÃtw,s¼Z$oÊN Ì@r¾ß%˹i šïkm*ö½ŒÖÐÃѩƊÁÈV9L}Õ½üœF¾úm.}(~H\¾®¥dXkéèÇ1{©¾‚6ŸqO`¹ŽÇ<'6qË·Ó¯ŠÖ¶ºõSN—»â«;»ç»emæhm.ÙÄ‚GÊ^Ê‘] {ÆÖÐïjÉ–ñYó¤VÖãDQd#cRhÞ(ªÛÊû…·ÏŸøR¤ÿûàÿì™üf¨¿ðúN^Áù,lö,—€gha—Nº ‚îΦï7ªS–ðxl=Ó.®ã¸ËÔ:Ü5ÅŽh«{< ã¼Wiò+w7åeÅa%ž¦y\!‰ÿÏ©$xCA¢¢Øá-î9_#œ¹.’åÓ\h Y©îë'WJµ"oÕŒŽ1äc'°Ó €ð¸Hê…zT?VòíÿÆWÄœ%ä_4õ“ýrô¬þ$«ékæž²®Aþ•ŸÄ•/¼¾–ˆŠ ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆˆ€ˆˆ(~³ÿã?Ü‚­¸èxßô° ª#œynû=Üûœ‘GÝøºø¥Í¯‡Jhc¾*âÂòÏ5X_Z¾ç$eÖížbÝ  sh:”î½—4DUþy囬™‹!gx›Ãš!@ç°µÍë"¥@ _6s–vWÐI ½ á‰eŒÄÍ€¸ê¦·Q£ûU}=ÂåÍx928gdÚÉjY$Öš¸m,Óô\h©Ø¼7OŽº°µ²}^øe†Y;-nºÑhÛPÔ0ePä\&[ûÑ·à¶qcµ±õ,×QØs¾2©ä Àç9 ¨i¹ïã‚èñ8ƒFªtWzúÚ¤ÉÉyGó(ˉ`îýí·:5?‰¡²Òœ:Vƒ­,YyDÝaù“˜ó¡÷önµoe’?IlL»ô¹Äê;÷ô¦1¬cXÁF´ÑÔÀ²Ep–¾Kø3árzìí§2Â㸆3+Ó²»æí_Î>ë5Ë ³ÉÕ—³Ä Üö†–ʦ’ÖM£mÚ)‚×Êá°ç C.ñ–ö’˜îƉ]fFBÚ¶F‚AWNMÁM†Æ9·@ «‡ñ$h èQ¬¨ßMþU`DÁkçÜ·ÊùÛd‚úêׇlÇJ]'7P>7µ½–¼ät$¼¯w6Œµ­Ÿ}lü^$f$.Ó¯Vïú &  ¹Ã>_ è-†«ˆ^Ù£ei¨´–ýLÅà9º|uÕ„l}­“ê÷Ã( 2ÈÑÙkuÐö‹FÚ€¾ ‰ƒ*‡"á2؇ތ…¿³ˆ‹­©fºŽÃñ•½T¢ù§¬Ÿë¥gñ%WŽ`²ÈßcoŒ¸î·EÍ"]o²Ѫ0J¦Üò3ÞH%»¾†â@4‡Ë,Ïph5¥]ÙµJ±ôTDUD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDD@DDDAÿÙsignond-nicolasfella/src/plugins/test/Captcha3.jpg0000664000175000017500000000541214615454535022440 0ustar coucoufcoucoufÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀ-j"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?õmN?&æÔZi­pŽFaƒÆÝ§?ž~µRæúê{õžMà!p[j—eàŽ8àð9àà‘šÕÔf’ÎX•Ö üÌåŠÿäŽþÙÀƒ«x‡I·p²Ú4÷A|à KF¤¶™ Ú9#'$g¯¨‹›=â†Óæ$ØpÀú½xéӑɪÚußÚt¹íNš ¶"–3!Hà¹ã¿4ýQ³Õb˜Ú‹ˆæ¶ àœºIìX>#¡äœf´&Ó’ì³)V,¤d69ëØç°=sϵcE%Þ©Ïpö‚XX´ˆÞfÂIÙÈÇPOÐ÷8èGË_²âVBY7¨Iîëúzõ¡;ZÙ ›By®Ø2®AÈëÐø'¥\¸QÔóZ]]̃$2ð)\“•ì9éÞ ñ¨Þè71è×oóº…yea¹|ün¶‚…À!x$Ù®.ïI¾ðÝÝÁ›S÷Öú}Æ¥ÍÅÄ€ylIRi8bÜÀë@wj–sÛ,P"烸zp8õî8¦Éá}*IÝ݉,Æá'Ö›k%ÅЄÄïk4¨‡y\©ÈÇleG }Ð=+HÙ\'Ϲçû¬ ~ ~ú}ZÌÄ&²[²ý¶¤@r£Ô÷"¼Ã_¼´}[RK«kh<Ùàžn—Ì·Kmå ÕYpÜr¹-Åz¶§¼h…í¼`©!<÷I1’™ÆH¯2¼Ò®ô—lÛ¤¦‹‰£o°¼°\E9%ƒ´*åwÃ.1<oøM¿‚îì%Ȇ]>tÿ"HœJé˜Ë#‚FÝûøê0zä=ºpc¸µˆ.y*àƒÏ·¦.¼ãÍü%¦]GqlòJ,â·Ó’È5Àòe¸pÅ·la»jýÕ߆9l^â+Kët.â7“‘–›9l‡ýŸóɇÅWRXhí%œ=JêE³³é4‡ Hè@ÜXû)ª?4;Kmkècù.e1Û–9aod'Õ¾y þô¦®ëºfµws¤]iíe<Ö7o3%ËNbxÁʃ’7žÃ¯·7|?h4 išC•’{;8àgU!]‘@'8èO?‰4ª¶Ûp O\íÏ?â3Dà,.ò´i ©.ÏÐrI=±šµIÖ'R»þãðUºt=ˆ~U‘ãx&»ð†¥ (ó3F<Èb夈02(I)¸c¾q@òxúÀÜÆRËRòXî‰#Áýà‡œÉßpNÙé]4SÇqMj‚h&ÍŽá]|· ÁÉ㞘ç>µå_Ú:‡‰Ò%°i/uTÔcÔc¸ŠFò"HDEo0”‚ Xçžzo jK…mb@=É·MŸ,™¥1¨ã òŒG @>¯{m¤é·W÷  hci&;ðv€IǩۻþùäÏ<—¾+¾—Ä~¦¡ÌS½•…Œ²ïÆZ8‹*Ú™,ÜüÒ7\%z%ÜZ^§c©i—2]*]Å$s¦ò@ʧîƒÉ8ê7}+ ÷ÁA e:Ž¢òä°yu;†R=T¾3Ç'·¦(sLÕ¿´´ûKÝ=/ßkn±RU”ç”Ã6õüja©Ü`yšV°ø€”c?÷جÍ?áµKI!†87€cmêùÜKù?Â[<}ãZ²ø§NŽWŒ˜²¬AýËžžàb€ ÔžöìÃö[ÈíÊd0·¶Êã¾=úÓ´ønV5/5Ü…½Ú6àp@Ž wì=jþ¹nB‰*¹ñîî;~²ÃYîò´rãvÕÉãwqÇZ­!¹ˆ¼òßEkÜä¨àç¶sýìtôëNþÒR±ÚÛ]4×%OÎv àdŒõäÌqÒ™¤I¥hn¤³"•aÈlŽ:ôçÚ£ÓçŽ]J[aX£n‰.NÞOýõÓÛÞ€,j7ÂÞžT‘Ô’û>aÆqÓ¨=ºwéY:éH^à\H‘£Ëo$ÁùGSÇéÐuµ©ÛÛ§‰mOÙá9.¼ þãéPëqA¬sGo»ÛD7,JIÀ=;`qéÇ,+Q Á‘Âà;m/·$ã8pwcý’8"²üe©ø–ÒÊ Í2c :É'“µ¥)µþ]¯ò‘¹¹IØpGZØH¢}´‘G#Éq·s $esßÜŸÌÔZ †D‘P¶…›p;“ï‚GÐâ€8|I©Ý›ùmf†æXš?µ X¡H£eýá‰DŽd”…1l8Îvžî £¥ØÛÙéì¦ÞXã€Äªèª…Ç ãøŽ:*ý¤[êrí@IT^x\à{÷íÀúÕ[ë;3¨‰E¬jË$„ìÆG?‚ñèI4"_%ä'ËšÚ9ÁãÚ̘ï‘õ=0xëȬÇ]BÂF‰ ݘ|Ñ:þéùÇËßhìN΃$V®§$í¬ašÝdà:t#Žú µ¯ïî_×E÷‡ÙŸû²ÿßrñT}™ÿ»/ý÷'ÿ]}}z_óî?øÿ/_éj}^=ßÜ¿®‹î9³?÷eÿ¾äÿâ¨û3ÿv_ûîOþ*ºúBªNJ©>¤húôºÓ_{òòõüêñîþåýt_qÈ}½$ÿ¿’ñt}½$ÿ¿’ñu×lOî¯ýò?‰ýÕÿ¾GøQõçÿ>×Þü¿àþaõxÿ7༿Ëòí¯#övô“þþIÿÅÑövô“þþIÿÅ×]±?º¿÷Èÿ 6'÷WþùáGןüû_{òÿƒøy‡Õ×óä«ËÏËòí¯"mÛÒQÿmú±¤û;Ó_ûøßã]~Äþêÿß#ü(ØŸÝ_ûä…^È¿ð'åþOðîÃêëù¿òUåçåùv×û;Ó_ûøßãGÙÛþšÿ߯ÿëö'÷WþùáFÄþêÿß#ü(úëþEÓí?/òÓaõuüßù*òóòü»kÈ}¿é¯ýüoñ¥6²¬V`­¤»€Ø8;Nppx8èx5×lOî¯ýò?—jñòŽ:p8úzRúì´÷Ÿ½.ËošóÓÕ‡Õ×óä«ËÏËòí¯#ögþì¿÷ÜŸüUfîËÿ}ÉÿÅW_E?¯Kþ}Çÿåëý-O«Ç»û—õÑ}Ç$¶’;*ªJYˆUää“€9|uõâ»íÙ¼çeERÅæ%ˆ$¶I$d“ÎM_°€îó˜| ™“Ópö ¤ôéÎÊÆíÛÔýkÎÅærQäŠP½ÝßÅ+]|’ûÝžÚùø¼/·œiÓr|—¿,9µ•–¶µ’Iyt{×’»/ý÷/ÿR%œ’cjKƒüEå ù–þY5Ó¬*>÷Ì!ùåS`z à–:_fõwòÙ}ûþ=JY"m:Õd—òÅ.o›»KN×~†V"0 îÞl£ì>qÇlõ<ôo³Iïì¿ü]lÑX^~_—mO«Ã¿àŒo³Iïì¿ü]!ƒh¼Áž™š^ñúÚªw_Ãþ}j£Zr”VŠïÏËm|¿.Ä΄c-ín‹«Håæÿ[/ýtýÑDßëeÿ®ÿ¡+º;/EùT·~¯ó8Ëo¾ŸõÕÿôcW_\…·ßOúêÿú1«àø(üö6ÿ‚ké~_Ú#Ç:„ÿÍɨ¤¥«i-ãÕøexÙy~Gé5üÖëÿð^_Ú0øbûâ/‚?àÿ¶f­ðÞÒ 5hµïYèÔn¼< Ìš‡ö%µÞ¯}²Z1†Þ+õ‰ŽÐó íŸðLø/ßìÝÿ2ø¥ªüðÉþ.hzU毫xGÆéìv¶ö3nPj¶Özx3Äà¬Mco$n °È¯1V¦ÚŠ–²øSRWôºWÝ<­_M·Õ¼ÔWÊ_¶ÅoÚWáÂÓâ_ÙcöfŸö¨ø’ú’Ú‡üIð/ÂÔ¶ÓMäòë3x‹Çú¾‘¤Ë½Ì6¶í§ÚËq©N.KÛÛJ#}¿ÂíyÿcÁP~ |Tñ×ÀûßÙ—ötøâß ê¯£kº~´þ%øŸâï ß[O ²Úx‚ÃÅ:/ƒ/ƲÅqö¿jv첓Ç&%Jð¥ñóyZ.ÏÉ;rßÊà¢ÞÖ?ÑvŠþy?gø*¿íûiüøo?ìSû*\|PñLþ ð¢|Nø÷ñbê/…_ôïÜé6Å#Ã1Ý4WÞ&‹LÕ'¸ce %ôßf@bµuÛ»Äþ?üÿƒœu;-kÆ~ý®ÿbm .ÏPÔ4Ï|9Ñ~ ÚjSE/r–—z÷-4»«°#Öò‹–I%o™°ù Û&“Œ*M5tã=.÷kgkë ùu³i|ÿÇ­êŠÿ1ïÙ³þ«ÿ‚ŽþΟÓÁ¿µ§ü _þh.¼ðßÄ=2 é~+´†Æö[Û¯ x‹BÕbÓ%šÞhüè ö“¨Cwn¾_–’:ºažÿ‚Ö¿íà 7ŰïìYûLþÒ—š”PÇqz|à¯hZƒÃ·š‡Œu‹A£ÜIjnb&ïm&ž-óB #íPÄÓšvm5¼Z|ß$¯{ukn¶»zôþ¿¤~êÑ_Ëoíÿwÿ‚Ã~Êñ ãüVêo‚Z~Ÿi©Ýê_ ü`¿uý#NšžæçÄGÂzγk¥If¬~ÕÊZ‹-’%êÄñÉ·éø%ïüKûÿÁJ|WmðŠÎ-oàWÇ«µ”i >#Üiп‹ä¶Œ½ÊøCY³¸¸Òõ; «$±èßkþÚ0Æî,ØFì)Vƒ’‹n2nÉJ.-½6º×ëAr»_uäÓ? )’IHÒJé(Ë<Œ¨Š=Y˜€¹4åe`He#!”‚=#‚=Åj!h¢Š(¢Ž0K2ª¨,îÄ*¢(Ë;3TrI É¡´µnË» ·½+BÚÂI]|Á±:œýæè=OO­s5ñ×þø3Xø…ãiZ„´ u]OÄ:Ü6úm¥œQ™ Ïxíäª2±Ë„n@ɯÄ}#þhÿ‚CÏñLü,Ö¿h±á›æ¿M:/jÞÖÇ€g‘¡câ¨-$³Ó#ŽU ÷H,ãFËuj̼5qZ5NËGïKvü—OW÷#™Vu&£Ë’ëžvm¥u{%¶ww®Èþ€Ò$@QÀÀã§ÀôªJüŽÿ‚…ÁZþ þdz_…¾7ü3}ö‹Ö~-j~ø%¢|;ñ>‹¬é>9×µx˜éf jÆò{'°’CgŠãÌftçPžŸÿÁA?àìðküxðÇüëÁš7Ãi|íOOð¦“kைÞ*—Dhþ×ÃxGÃþ<¼ñ´¶ÑÚ æäéQ¸"E+æ)AæÝ½ÝÎøÆ1VŠIy$¯æû¿7«?¸z+øÃÿ‚wÁÜ >"xú?€ðRß„ò~É?¢Ô“@_‰š}¶¸ß £Ö¢[ˆæ°ø…á½fÜø³á½ä—1[[G}·]Ñ ÕãÉ©Iá½>ØÎßÙF‰­èÞ%Ñ´ŸxwVÓuïëÚm–±¢kz=õ¶§¤kN¥mæªiz•”³Ùê}ý¤ÐÝY^ÚM5µÕ¼±Ï²Dêä(Ô¢Š(¢Š(¢Š(¢Š(¢Š(ªw_Ãþ}jåRº<ÜUÓøãêg[ørù~hæ&ÿ[/ýtýÑDßëeÿ®ÿ¡+ÔŽËÑ~G‰-ß«üÎ.Üá‘$„ßǯóø1û[|7øÿ;øÏã‡íñ©Ákàö¦øáðóC5Xî¼9ðÙ¾Íâï‡t]bÞêÖÞ k aø{Mkï°Z•ñiâ è#¸’òJÿO ½ÿmdÿÐÚ¿Šïø.wüã¯ÚKãgÄÛCöÕ4(üsñ;S¸ñÅ‚:íÀÑáÖ|sx±I­øÇÁó“k ÿНüíoÄVªmÔësêì¿Ú §Ù÷fð›xyÁsrIÉýšw·^ÎÚÛ¿OK×+OK¥­íÓî?¶MSðωtKGú†‰¯xsS³ótÛíêÇSÑïìOîL–W6RMgsmÁˆ¼.ñ‚  ~7üÿ‚Dh?ÿàªÿà ^ Õ¼¡øâ×ý;A‹áž‰§^ÙjºŽÓK¯xšR–qèég¬Eå–†ÚãÎò4_¼&¿ÎNÿÆðZoø$¾»i»¬~Ò4m>ú·ƒW¸Ö5Ÿ†Ú‹Z0Df¾ÑDc ,örM°8Ç'ûÿƒwà¹þ5ÿ‚—Úx×à_í¦i:džÚ5ž·§ø‹BˆÛiþ<ðÁÞêöîÇq:ÕÊÿ¤ˆZÜÂË*äßóá^gÔ„¡8¾h§üÖ{=É«>§C‹Šm;¦µôüOé ã¯ÅmàgÁ¿‰ß³ðÇPñÿŠ>0üa¾sð¬z´÷n‰–IV¸{K!ºx"†Ý§˜JXCo?÷/ÿ@|u¿ø'ÿ—øÃk¦ÝMcuñgÄ^øYçÄY|û}rýï®ôÖt"Dû]®™,¬ÈÃt“ÄᣑÅ|ÿsþÌú/¿bo‰ß´¬¶pÂOñ·âN¥áè/ŠæðøcÀOý™¹bH­²u¹²Ã-ê°Y£Ê¬½®"'ðÅsÉw×oÁ-m£a"å×§åùþGõÇàOxCá—ƒü;àøwI𧃼'¤Ùhžðþ‡cm¦éšf›a[Û[ÛYÙÅ ªÇ,R529gl³”ø83þ ªÿ³m¥ßì3ûÜ7Œÿj/‰6ÖÚ½«xqµäð5·ˆm54{¬ ËÜø»Rya†ÏL­ÐyQŠ™EÏîoüöÆ·ý„`Ïß´Tr ñ†ü*ú?‚áy ŒMãM‡ “çî,°^^¤ûa‚ye•"·U‹ÎûLÊ/üËûØþÓ^3ø¡ÿTý¦ìOÄO]üA×4ï…øœ®«>*‚áŸÄ>/û=û^ ‰ô©çm7E™£Œi·–ò5¥Á¹±’+{­)9F…7iM]ËùbŸe®ªë§®öQI''­¶^z‡üOþ ‡m:÷Dý®?à¥ú,~ ñž¸é⟠þÎzÄ[íô‹ëû™/ÛXø´cE©kW ñL|!K9Úê-zMBâìý7ûHñOŒ¾ þέï|S®x+á7Ãhéi§Çu&›á¿èº.‡eqÙé:t+oooe¥éðÄ«i§[lí"LG¾ÿý¶¾Á=¿e/‰ß´ïĦŽãOðV·‡<=æ47,ñޝ/Ù<=áÛVE$=ÝÓ=ÍÉXYÞXÎ"Fþ/bÙ—öÆÿƒ’¾'xöšýµ>(x·Àÿ±NƒâÉlü+ð¿Â·óiÚgˆäÒç–DÒ­´ï1-náÓ#–+hµ;Ë{Ûn'ÔdŠßír.W¹C–•(sT’¿m?šrí¦Ëä–—zËY;%ýY™úÕûpÿÁп±ç‚-¼Að‹öN𯉿k߉Úлðœ^ÑæÔ|uGÌÓà´:øS¤êâìÊ­btK½jåæ)ºV÷Toä«öQÿ‚!Á\j¿Ú?Mý¡tÙ¿Ç_³5Ž¡ñ7þxÓÇÑ\|_ Îu´ÖRëB²ñ ÐüI{Ö"ÚÿÃ:§m3)kå—‰Ò§öký‡b¯ø'÷€f‹àOÁ‡? t¿èn‹g¿Ôôß…úv¿ ÒØLm4é÷>&ñæ§Þ íõޱáeçOñ-Õ‰KÆŠ´Óå–"­šøcN=ít´rwk{/ÓéüÛüÿà?‘ý<ÿ¶¹ñwÁøTÿu{Ýø‹áÐðWŽõÍ1ßG»Õ.5i:棧Íjþe…Ô²É=ŵÔ,¯û.#HÎ#_áãþ û]ÁOà?|¤|4ý«ïjÙ‹âm¬×ÞðçÇ+;øËÁriÇç‚5­fí§Õæ°HÚçGñwh. š]>`×v7Lÿ¦ üoû@øbßÄ~'ø©ÿÞÿ‚wé—b).,N“?Œ|eie$-1º‹Oñ7‡ÿi? #Ki©ø·N¾™·GÆÊŸŸ¿?à‚~.ý©¾ h?¿à§Ÿð\O|_Ôt{Ò«áíÃúΓoos*=ö“ákTøàíÁò_4J¸Ñ¼ÑK")“L¸*#§VRœR§ šµ§&©Ú=S¼“jÝÖ›îÂ:^í4ú+½tòóGôUÿxÿ‚‹ükÿ‚ƒ|³ø‹ñÛà=¯Â-gS³±Ö¼#â_ êrêþñöƒ{FSd.ÞMSÃ~%Ñï ¶Ú·‡µY%‘còn!œHgµ·ý ø¯ûEüø>‰Æ?ˆþøm‰.ž…¨x¶åôQ¼.‰öHµ‰âþ̆çs¨òn® vC";/æwÁ/Ú/þ ÁÿÑýœ4¿ƒþ øŸã›¿‡¿ íÞYuKÿ‡Ÿõ¦½»»{˯[x Eð ³]¤ ¼Òjšu¤–öц¹¢y›ùCÿ‚÷Áw|!ûø þ²WÀ[ÿ[ë:§‡5ÛÿŠšž¿à¿xž VÃWšUÓü£|)ñÄ X-Õœ0Û^ëzÇŒ ×¬¡ÔïôûŸ é2ˆ¯n.U•*KšqNU¦üϳåùëùîÒå³Kúîr¶íK¯~Ì_õŽžø5ãÚÃ]‚jšŒ Hñ.³g¤O Om¯Á ép]êî‚Ñ8žæÿC7dµÅäÑ­žë„þ\Ûþ6øÇûfÞü[ý”?gÿ:ßÃ_Ú;Äz¤ß¥×õ믇Î=Å®¿c¯Çâ»'¸·v÷ð\ÚfÙ}«í#Y»¶´E¸oÓ_ø7áGíŸðwöðï‚ÿjû{û*7_tOÉqu¬xÃ×RO2i–óߟ·¶œVD¡»!·žfŠÉî!Þ¼wþ ùìáâ?‡~ø7ð;á~—ñ þ =¬|Hðµçì×kðcC²o‹>׎½¦M­kZ®»áë9u æE&¡®XßOoowm§­Î¡&™h?µ U\çIMIÁ8^TÚM»ôNÊíôMjô²¾‰Å4àÕïÕ]õM]]i}%f´ºësùÚñí¥ÿmýŠÿdÏ_²üsövý¢&ýš¾1ǯÃðËöЏÓ%ñÿÂ?ë3\ϧøOþ*øD¼Qà-g]‘–ojšÆŸâ­ÒùõWF‡Hðäÿ}ÿÁ¿àŽÿðCø)÷ìG-ݦƒâ»ÿº-Ûé¿üCáߊ0Ð>!xSY0ÙjÚ?‡5íGZÒìô-K-›j>Ôì.%†Xd2í1§ö=ð?៉üoû$ø+áGís øwâˆü&ÔìüUñªËáÕÅdž'ñN“o5´vß¼8šØË£xïÃ7éZæ§¥íºÖí&]JèÃ>{4ÊWÝþC¡Šm¨Tz½#>ì”ÿù%o4ÏÝŸø*ü¿ö'ÿ‚¨xRêóâ'„í¾~Ðv6Ó¯„i‡ZE…§Žlå’ ©§øëOF±°øá,pL4¯Lº®œc•|3â/ CV:‡òIû-~ÜðQÏø6öƒÑc¯ø('†¼Añ›öñn§yoðóÅú Î¥â #ÃzZ_î“Æ|G©¤,-â¹û_¾ k‰cwfn×SÑ¡ÒïÔ¿‰?u?àÛø.&³ÿøe«~ο´v©a'íSðWA°¸“Ä8µ°—âÏaòôø9üñæƒñ'áw´¨µo x«Ã×iuis·Wq.4Ý_M¸e«iñA¨i·±KkyoѲױWù•~Á´÷íÿØÁV¼Qû~Ñ>(Õ¼Iû|OñΑ§kWWžd®‡âÛ…²ðÇÿ Ú]Ì4í2úÎ),ì~!ZØÞEo6o~.¥žçEÓâoôͳ»µÔ--oìn"»²½·‚îÎêY`¹µ¹‰f·¸†E%dŠh$Ô•te`H"‘EŠ(¢€ (¢€ (¢€ (¢€ ¡u÷ÇÓü*ýSºþóëZRvšóÓï2¬¿vüš¿S–—™d>®ÿú¢–oõ²ÿ×GÿÐéÇeè¿#Å–ïÕþgn2Ê=eäF¯Àïø7Sþ =ã/Û[ömøµðsö…ø¦ÿ¿k?Ù3ãWüñÄí¶¢ø¿Ç¾Õ|U¬j>#_x{L·´Ótë5f×~‹-2›ÿ«êÒµÞ­mw¨~øÛ}ôÿ®¯ÿ£¿”/ŸðmWÆÿ…?¶GŠo¯ø$·íϨþÌ|[âßøÛUðÅÍëÅ }cÇúÍïˆ|_¢Çã .ÇÄj õ}Nâ&o‡ß~üE‰$† ùµû«;LŠ×Ó̹ã<<á(¥QN)«µ.K4“i®û]u= -¹z?vÏåúŸÓ·íð áGíðƒÇ¿ þ/øcCñ„3qyioñgá¾¢Ö÷¶[ÙÖçQ±Š;QÒI#‚þòVCè®2TaŸðj‡Æ/‡¾.ÿ‚N|&ðU‡ˆ<3Žü㉞ño‡àÔl¡Ö£¾1Õ.4).´âñÝ4·žÞ$‚) É8¹,Bý;ÿ.ÿ‚|ÿ‚œ|MÐ>!|Zø»ñƒÂöZ?†í¼?sàŸ x¬|#¨=¥Ô÷0j’im4+¨âæX%¹%žhÕþ=b#äÿÙãþ vý”fˆÞø©ðƒãÏíàÿø?]Óµû ô¯_ÛXÞ\i÷¶×†ÏV±±¸ÓRÿMÔÕ,õ;VxÝ‹ËnedܭƯÖEâ£Éñ¤Ú½ù–š[¶×ê Ç–×ß]ž›hyüa¬êðNÏ£jV‘Yh?|7}â{íHm¯n,ntûÛ(ÄÜ$·p5íÔw“ †WV°·d)N³}­ÿÌüAøoãø$Oìå§xêÁ¯<¾/ðÇtÛe¶†óLñM—‹µ¨îÎ¥kÙ£ºÕ ŽÛWk›”WÔõ¯£/ Ñ»zGüÇþoû=ÿÁO#?´_ìѪxcà÷í7rñCãW¾µ{|J³Š‰u ^-"’×Åyùnu­’¾¨²/·\,Ó\˜Šs“…Zjó…ý×Õ>Þkþé&E­žÍßç¦Èïàš¿°·‹ÿnŸƒ^ý¶?à£?¼uñ߯?ìâñW…¾i~/×¼3ð[ÀÞ’îðYéVþÑ/ííõy&EŽ;ÆÕïuX\ÚDÑÃe+]E)ÿÏñ…ÿÄý‚õ?‰±Ïì½ðsEñMÖ«cáIüvŸ ü5â+ÏXß‘:ô—z•†£qsx×3G3jP^Á%¹¹¸¶Xc}Ïÿ`ýžÿlÙ'öHðçìÑûZÚøVóPøTϤøÅ~ñ ×aÖ|7,Òͽärª]ÚÜY»dÒq,ŽL.¢9Oþ&ü2ð'Æ?x£á§Ä¿ i1ðGŒt{í Ä>×, ¿°¿Óõ y-§áV@’†d ,2’7WPjãNôl“ŒÜu”—¼¥m[o]úß`nÒÞé=“ÒÝ<´üÏò<ý¾|lÿ‚Øþܾø1ûT~Õ~5“LÖ"½¸¼¾×|G#\¦“lys¡xÃØC´žDƒ0i¶|6ácVdŠ(ŒÑÿnWv¿ðEßø!,þ øOðÛà.¡ñÛöÉÕ4uøῃ-¾.þÑÞ:ÕáŒznµãѼn>k‹›‹WÓÞÉn$¶³½òü‰??à¡ßðlGí3û'üM‡ö­ÿ‚Fë:ö¼¾Ô“ÄÂ{OÃcñ7Â¡Ëø+TÕîí ñ5´#ä›H¸½MJ[u&ºpÑ¿¨ÿÁfø(Gü<ûÆŸ´ü;öVø»¤øÓÅþ¹GÅOxEbÒt¿#ZÛJÖ³-ãZé2ßéËy5íý¤‡|ã÷º}༚æËޤù'M*’Ÿñf¹â¡Õ¯5nýuµ’¥¹œ­¶n×}Ÿù|ÏèoÃ:gü·öÝÓà¼ø™uðçþ ¥ð;Zµ³¾Ox añ§ö³Õì®’F›I×¼a­AcðÇÀ6÷rÄ—K¤xcSñ•Øu†ý;~öý˜¿`Ï€?³ŸYð/‡u{â«O|_ø…©Íâï‰Þ)‘Ý¥–MOÅ‚}¤Äe’C ­ªÛÛ[ÂÉlŠbŠ5_µ!±†0 1ÇsÂ@8Æ?½»‘‘Žu §±±»¼ŽÚ{Ù-­å--‚›‹§ $‡*¾d¬)bœ Öu⟹yK_~zÛo†:%÷+v8*bþÍ5§v¬ºj–ïÖ_qñWüKö½Ðÿa?Ù âÿí¨EÖ¡àß ] i’òºŸŠ¯PÛhÐ8*áâŠêT»¹ ¬¿g‚@Uø¿ÉöM¹ñ¯ü3þ ¥ð£Ä_õ[­oÄ_þ?iž4ñUÝÌÒ¾Ûk}q5ǵAæ–¶ñ[Ål¶ÈVÝÊ]Ðÿ~ÿðX?ÿÁA?oÿÙ×âwì‰ðsþ AñÆk}gXŽ-'â7ü ð·†éw2E³gáçñ-Æ·}eui4ÏÙ· °ŽXŠïŠOæoö!ÿƒr¿àµß³Ç´‡¾ü-ð߉~kQëuŒþ(øRkI£x&†àèwÚ«FZ $Q",ê¬WÌŠâ’â•Ü–ï[·®íõÿ?1Ðq„*JsŠ©;Ù¹Åɦ“îÚ»zß_Vôððî›áýH¶UK}3IÓì!TPGki q„Ï>¹95À|xð&•ñ?àŸÅ¯‡šÝµþ—ãO‡^1ðåÕ¥ØCm(ÕtëXŒ¢B#ÛòE(2Ê‚+åOÙG\ÿ‚“kÞ'~×þýš¾ø&×Ãó$ZwÂø¯Åþ*Ô|@ZÚ;I.µmVK]6ÞÒÖêkÁ—ºêY!XZÝbs7ŽþÜ¿²×üö’ñ\ºìñûwi_²gÁ+ÍéZÞែþñ¿õÙ®„±jR7‹<\×£H¶žÖO³Ç•gmsúÈîã“çkþ¿«ØãQ÷’rŠÙ·{¥÷'v»+Ÿæ…ÿsø•âÙ3þ Wð6ÛDÔ$Ñ4ÓñËÄÿ |EkâÒÖçÂÚûkZDz}ç̱ xn—qå»Iíc€¸?ì[ «Å£+«(*ÊÁ•”ô*ÂÆ$zþ->ÿÁ›?³ï‡¶ýëý]MËhËÿ?þûãGöŒ¿óð?ï±þ5Íõ*ŸÍÇü¿«?+ëíáçÓôÿ?êèêh®[ûF_ùø÷Øÿ?´eÿŸÿ}ñ£êU?šùV~W=¼<ú~Ÿçý]MËhËÿ?þûãGöŒ¿óð?ï±þ4}J§óCñÿ/êÏÊç·‡ŸOÓüÿ«£©¢¹oíçàßcühþÑ—þ~ýö?Æ©Tþh~?åýYù\öðóéúŸõtu4W-ý£/üüûìiÚ ™ñ$·\%r§Ì]ïœà¨$í_â˘ÚmËÂÊœy§8%ó»}’¶¯Ó³{SF”y§.U÷¶ôÑ%«z½º+í©®ªÌB¨,Äà2I«ÑXHüÈ|±éÕ»öè;u=*´s,@•Ü¥^¬IcÔõ>Ý*_¶7üüûík†~ÕéO•/æz¾,ÒÝ÷ÛÌóç›ÅéNKù›éÓT·}öó5bµ†,@Xrsê3Ÿ÷@þy±X_loùø÷ÚÑöÆÿŸÿ}­r¼=Y;Êi¿6ßo/_»ÌåxøÉÞJmù»öÿƒ÷y›´VÛþ~ýö´}±¿çàßkKêµ;Çï~^^oîó×iÿ,¿/ów™»Esæó“™Î~§ú ~TŸlóØþgü)ýV]eŸ§ŸŸà» úí?å—áåþoîó:+žû`ÿžÇó?áGÛüö?™ÿ >­/çOÓÏÏúº®ÓþY~_æþï3©z±Ãúÿ<ž,V"\ Ut Ϙ¼ñדÞö¥ÿžéÿ}¯ø×,¨M»Ý[¦ûiåçø®çÐQ« tãµµäÝùö^I4V7Ú—þ{§ýö¿ãGÚ—þ{§ýö¿ãKêóî¿//?˾šýb¿lÑXßj_ùîŸ÷Úÿ/ÚÓþzÇÿ}þ*a?'÷ùyyþ]Ãëþš6(¬Ÿ¶ÒhÇü ƶùíýö¿üU/aSËñòòóþ®®þ±é¯/ów™­Edý´Ïhÿïµÿâ¨ûhÿžÑÿßkÿÅQì*y~>^^ÕÕϬSïø¯/ów™­Edý´Ïhÿïµÿâ¨ûhÿžÑÿßkÿÅQì*y~>^^ÕÕϬSïø¯/ów™­TüúÕ_¶ùíýö¿üU1î‘ñºXÎ:|ëþ5P£5$ݬúùyyÿZ^'Z‹Šz»u]ç÷“­—þº?þ„h¢R ²AG ŽAŽ=Á¢»ÖËÑSÝú¿ÌÿÙsignond-nicolasfella/src/plugins/test/captcha-images.qrc0000664000175000017500000000026214615454535023663 0ustar coucoufcoucouf Captcha1.jpg Captcha2.jpg Captcha3.jpg Captcha4.jpg signond-nicolasfella/src/plugins/test/ssotest.pro0000664000175000017500000000023414615454535022533 0ustar coucoufcoucoufTARGET = ssotestplugin include( ../plugins.pri ) HEADERS += ssotestplugin.h SOURCES += ssotestplugin.cpp headers.files = $$HEADERS INSTALLS += headers signond-nicolasfella/src/plugins/test/ssotest2.pro0000664000175000017500000000034714615454535022622 0ustar coucoufcoucoufTARGET = ssotest2plugin include( ../plugins.pri ) QT += gui HEADERS += ssotest2plugin.h \ ssotest2data.h SOURCES += ssotest2plugin.cpp headers.files = $$HEADERS INSTALLS += headers RESOURCES += captcha-images.qrc signond-nicolasfella/src/plugins/test/ssotest2data.h0000664000175000017500000000241214615454535023076 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SSOTEST2DATA_H #define SSOTEST2DATA_H #include "SignOn/sessiondata.h" namespace SsoTest2PluginNS { class SsoTest2Data: public SignOn::SessionData { public: SIGNON_SESSION_DECLARE_PROPERTY(QStringList, ChainOfStates); SIGNON_SESSION_DECLARE_PROPERTY(quint32, CurrentState); SIGNON_SESSION_DECLARE_PROPERTY(QStringList, ChainOfResults); }; } // namespace SsoTest2PluginNS #endif // SSOTEST2DATA_H signond-nicolasfella/src/plugins/test/ssotest2plugin.cpp0000664000175000017500000001612214615454535024021 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include "ssotest2plugin.h" #include "ssotest2data.h" #include "SignOn/signonplugincommon.h" #include "SignOn/uisessiondata.h" #include "SignOn/uisessiondata_priv.h" using namespace SignOn; namespace SsoTest2PluginNS { static QMutex mutex; static bool is_canceled = false; static QEventLoop uiLoop; static SignOn::UiSessionData uiData; SsoTest2Plugin::SsoTest2Plugin(QObject *parent): AuthPluginInterface(parent) { TRACE(); m_type = QLatin1String("ssotest2"); m_mechanisms = QStringList(QLatin1String("mech1")); m_mechanisms += QLatin1String("mech2"); m_mechanisms += QLatin1String("mech3"); qRegisterMetaType("SignOn::SessionData"); } SsoTest2Plugin::~SsoTest2Plugin() { } void SsoTest2Plugin::cancel() { TRACE(); QMutexLocker locker(&mutex); is_canceled = true; if (uiLoop.isRunning()) uiLoop.quit(); } /* * dummy plugin is used for testing purposes only * */ void SsoTest2Plugin::process(const SignOn::SessionData &inData, const QString &mechanism) { if (! mechanisms().contains(mechanism) ) { emit error(Error::MechanismNotAvailable); return; } QMetaObject::invokeMethod(this, "execProcess", Qt::QueuedConnection, Q_ARG(SignOn::SessionData, inData), Q_ARG(QString, mechanism)); } static QByteArray loadImage(const QString &name) { //TODO: adopt to something changeable QString resource = QLatin1String(":/"); QByteArray ba; QImage realImage(resource + name); QBuffer buffer(&ba); buffer.open(QIODevice::ReadWrite); ba.clear(); realImage.save(&buffer); return ba; } static QVariantMap nameToParameters(const QString &dialogName) { QVariantMap data; if (dialogName == QLatin1String("Browser")) { static int ii = 0; ii++; if (ii % 2) data["OpenUrl"] = "www.yahoo.com"; else data["OpenUrl"] = "www.google.com"; data["watchdog"] = QString(SSOUI_KEY_SLOT_ACCEPT); } else if (dialogName == QLatin1String("Login")) { data["UserName"] = "testUsername"; data["Secret"] = "testSecret"; data["QueryMessageId"] = 0; data["QueryUserName"] = true; data["QueryPassword"] = true; data["watchdog"] = QString(SSOUI_KEY_SLOT_ACCEPT); } else if (dialogName == QLatin1String("Captcha")) { data["QueryMessageId"] = 0; data["CaptchaImage"] = loadImage("Captcha1.jpg"); data["watchdog"] = QString(SSOUI_KEY_SLOT_REJECT); } else if (dialogName == QLatin1String("LoginAndCaptcha")) { data["UserName"] = "testUsername"; data["Secret"] = "testSecret"; data["QueryMessageId"] = 0; data["QueryUserName"] = true; data["QueryPassword"] = true; data["QueryMessageId"] = 0; data["CaptchaImage"] = loadImage("Captcha1.jpg"); data["watchdog"] = QString(SSOUI_KEY_SLOT_REJECT); } return data; } void SsoTest2Plugin::execProcess(const SignOn::SessionData &inData, const QString &mechanism) { Q_UNUSED(mechanism); int err; SsoTest2Data testData = inData.data(); QStringList chainOfResults; for (int i = 0; i < testData.ChainOfStates().length(); i++) if (!is_canceled) { quint32 currState = testData.CurrentState(); QString message = QString("message from plugin, state : %1").arg(currState); TRACE() << message; emit statusChanged(PLUGIN_STATE_WAITING, message); usleep(0.1 * 1000000); QString dialogName = testData.ChainOfStates().at(currState); QVariantMap parameters = nameToParameters(dialogName); SignOn::UiSessionData data(parameters); emit userActionRequired(data); uiLoop.exec(); int errorCode = data.QueryErrorCode(); if ( dialogName == QLatin1String("Browser") ) { if ( errorCode == SignOn::QUERY_ERROR_NONE || errorCode == SignOn::QUERY_ERROR_BAD_URL ) chainOfResults.append(QLatin1String("OK")); else chainOfResults.append(QString("FAIL")); } else if ( dialogName == QLatin1String("Login") ) { if (errorCode == SignOn::QUERY_ERROR_NONE) chainOfResults.append(QLatin1String("OK")); else chainOfResults.append(QString("FAIL")); } else if ( dialogName == QLatin1String("Captcha") || dialogName == QLatin1String("LoginAndCaptcha") ) { if (errorCode == SignOn::QUERY_ERROR_CANCELED) chainOfResults.append(QLatin1String("OK")); else chainOfResults.append(QLatin1String("FAIL")); } testData.setCurrentState(currState+1); } if (is_canceled) { TRACE() << "Operation is canceled"; QMutexLocker locker(&mutex); is_canceled = false; emit error(Error::SessionCanceled); return; } if (!testData.ChainOfStates().length() || testData.CurrentState() >= (quint32)testData.ChainOfStates().length()) { err = 0; } testData.setSecret("testSecret_after_test"); foreach(QString key, testData.propertyNames()) TRACE() << key << ": " << testData.getProperty(key); TRACE() << "Emit the signal"; if (err) emit error(err); else emit result(testData); } void SsoTest2Plugin::userActionFinished(const SignOn::UiSessionData &data) { TRACE(); uiData = data; uiLoop.quit(); TRACE() << "Completed"; } void SsoTest2Plugin::refresh(const SignOn::UiSessionData &data) { TRACE(); static int ii = 2; uiData = data; QString imageName = QString("Captcha%1.jpg").arg(ii); TRACE() << imageName; uiData.setCaptchaImage(loadImage(imageName)); ii++; if (ii>4) ii = 1; emit refreshed(uiData); TRACE() << "Completed"; } SIGNON_DECL_AUTH_PLUGIN(SsoTest2Plugin) } //namespace SsoTest2PluginNS signond-nicolasfella/src/plugins/test/ssotest2plugin.h0000664000175000017500000000343414615454535023470 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SSOTEST2PLUGIN_H_ #define SSOTEST2PLUGIN_H_ #include #include "ssotest2data.h" #include "SignOn/authpluginif.h" namespace SsoTest2PluginNS { class SsoTest2Plugin: public AuthPluginInterface { Q_OBJECT Q_INTERFACES(AuthPluginInterface) public: SsoTest2Plugin(QObject *parent = 0); virtual ~SsoTest2Plugin(); public Q_SLOTS: QString type() const { return m_type; } QStringList mechanisms() const { return m_mechanisms; } void cancel(); void process(const SignOn::SessionData &inData, const QString &mechanism = 0); void userActionFinished(const SignOn::UiSessionData &data); void refresh(const SignOn::UiSessionData &data); private: QString m_type; QStringList m_mechanisms; private Q_SLOTS: void execProcess(const SignOn::SessionData &inData, const QString &mechanism); }; } //namespace SsoTest2PluginNS #endif /* SSOTEST2PLUGIN_H_ */ signond-nicolasfella/src/plugins/test/ssotestplugin.cpp0000664000175000017500000000757514615454535023753 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include "ssotestplugin.h" #include "SignOn/signonplugincommon.h" using namespace SignOn; namespace SsoTestPluginNS { SsoTestPlugin::SsoTestPlugin(QObject *parent): AuthPluginInterface(parent) { TRACE(); m_type = QLatin1String("ssotest"); m_mechanisms = QStringList(QLatin1String("mech1")); m_mechanisms += QLatin1String("mech2"); m_mechanisms += QLatin1String("mech3"); m_mechanisms += QLatin1String("BLOB"); qRegisterMetaType("SignOn::SessionData"); QObject::connect(&m_timer, SIGNAL(timeout()), this, SLOT(execProcess())); } SsoTestPlugin::~SsoTestPlugin() { } void SsoTestPlugin::cancel() { TRACE() << "Operation is canceled"; emit error(Error(Error::SessionCanceled, QLatin1String("The operation is canceled"))); m_timer.stop(); } /* * dummy plugin is used for testing purposes only */ void SsoTestPlugin::process(const SignOn::SessionData &inData, const QString &mechanism) { if (!mechanisms().contains(mechanism)) { QString message = QLatin1String("The given mechanism is unavailable"); TRACE() << message; emit error(Error(Error::MechanismNotAvailable, message)); return; } m_data = inData; m_mechanism = mechanism; m_statusCounter = 0; m_timer.setInterval(100); m_timer.setSingleShot(false); m_timer.start(); } void SsoTestPlugin::execProcess() { m_statusCounter++; emit statusChanged(PLUGIN_STATE_WAITING, QLatin1String("hello from the test plugin")); if (m_statusCounter < 10) return; m_timer.stop(); SignOn::SessionData outData(m_data); outData.setRealm("testRealm_after_test"); if (m_mechanism == QLatin1String("BLOB")) { emit result(outData); return; } foreach(QString key, outData.propertyNames()) TRACE() << key << ": " << outData.getProperty(key); if (m_mechanism == QLatin1String("mech1")) { emit result(outData); return; } if (m_mechanism == QLatin1String("mech2")) { SignOn::UiSessionData data; data.setQueryPassword(true); emit userActionRequired(data); return; } emit result(outData); } void SsoTestPlugin::userActionFinished(const SignOn::UiSessionData &data) { TRACE(); if (data.QueryErrorCode() == QUERY_ERROR_NONE) { SignOn::SessionData response; response.setUserName(data.UserName()); response.setSecret(data.Secret()); emit result(response); return; } if (data.QueryErrorCode() == QUERY_ERROR_FORBIDDEN) emit error(Error(Error::NotAuthorized, QLatin1String("userActionFinished forbidden "))); else emit error(Error(Error::UserInteraction, QLatin1String("userActionFinished error: ") + QString::number(data.QueryErrorCode()))); return; } SIGNON_DECL_AUTH_PLUGIN(SsoTestPlugin) } //namespace SsoTestPluginNS signond-nicolasfella/src/plugins/test/ssotestplugin.h0000664000175000017500000000343514615454535023407 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SSOTESTPLUGIN_H_ #define SSOTESTPLUGIN_H_ #include #include "SignOn/sessiondata.h" #include "SignOn/authpluginif.h" #include "SignOn/uisessiondata.h" namespace SsoTestPluginNS { class SsoTestPlugin: public AuthPluginInterface { Q_OBJECT Q_INTERFACES(AuthPluginInterface) public: SsoTestPlugin(QObject *parent = 0); virtual ~SsoTestPlugin(); public Q_SLOTS: QString type() const { return m_type; } QStringList mechanisms() const { return m_mechanisms; } void cancel(); void process(const SignOn::SessionData &inData, const QString &mechanism = 0); void userActionFinished(const SignOn::UiSessionData &data); private: QString m_type; QStringList m_mechanisms; SignOn::SessionData m_data; QString m_mechanism; QTimer m_timer; int m_statusCounter; private Q_SLOTS: void execProcess(); }; } //namespace SsoTestPluginNS #endif /* SSOTESTPLUGIN_H_ */ signond-nicolasfella/src/plugins/test/test.pro0000664000175000017500000000010214615454535022000 0ustar coucoufcoucoufTEMPLATE = subdirs SUBDIRS = \ ssotest.pro \ ssotest2.pro signond-nicolasfella/src/remotepluginprocess/0000775000175000017500000000000014615454535021757 5ustar coucoufcoucoufsignond-nicolasfella/src/remotepluginprocess/debug.cpp0000664000175000017500000000207114615454535023551 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "debug.h" #include #include int debugLevel = -1; void debugInit() { if (debugLevel >= 0) return; QString ssoDebug(qgetenv("SSO_DEBUG")); debugLevel = ssoDebug.toInt(); } signond-nicolasfella/src/remotepluginprocess/debug.h0000664000175000017500000000251114615454535023215 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef REMOTEPLUGINPROCESS_DEBUG_H #define REMOTEPLUGINPROCESS_DEBUG_H #include #ifdef DEBUG_ENABLED extern int debugLevel; #define TRACE() \ if (debugLevel >= 2) qDebug() << __FILE__ << __LINE__ << __func__ #define BLAME() \ if (debugLevel >= 1) qCritical() << __FILE__ << __LINE__ << __func__ #else #define TRACE() while (0) qDebug() #define BLAME() while (0) qDebug() #endif void debugInit(); #endif /* REMOTEPLUGINPROCESS_DEBUG_H */ signond-nicolasfella/src/remotepluginprocess/main.cpp0000664000175000017500000000532514615454535023414 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ extern "C" { #include #include #include #include #include #include #include #include } #include "debug.h" #include "remotepluginprocess.h" #include using namespace RemotePluginProcessNS; RemotePluginProcess *process = NULL; void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString & msg) { Q_UNUSED(context); if (debugLevel < 2) { if (type == QtDebugMsg) return; if (debugLevel < 1 && type == QtWarningMsg) return; } int priority; switch (type) { case QtWarningMsg: priority = LOG_WARNING; break; case QtCriticalMsg: priority = LOG_CRIT; break; case QtFatalMsg: priority = LOG_EMERG; break; case QtDebugMsg: /* fall through */ default: priority = LOG_INFO; break; } syslog(priority, "%s", msg.toUtf8().constData()); } int main(int argc, char *argv[]) { openlog(NULL, LOG_CONS | LOG_PID, LOG_DAEMON); qInstallMessageHandler(messageHandler); debugInit(); TRACE() << "handler:" << (void *)messageHandler; #ifndef NO_SIGNON_USER if (!::getuid()) { BLAME() << argv[0] << " cannot be started with root priviledges!!!"; exit(2); } #endif QCoreApplication app(argc, argv); if (argc < 2) { TRACE() << "Type of plugin is not specified"; exit(1); } QString type = app.arguments().at(1); TRACE() << type; fcntl(fileno(stdin), F_SETFL, fcntl(fileno(stdin), F_GETFL, 0) | O_NONBLOCK); process = RemotePluginProcess::createRemotePluginProcess(type, &app); if (!process) return 1; fprintf(stdout, "process started"); fflush(stdout); QObject::connect(process, SIGNAL(processStopped()), &app, SLOT(quit())); int ret = app.exec(); closelog(); return ret; } signond-nicolasfella/src/remotepluginprocess/my-network-proxy-factory.cpp0000664000175000017500000001217714615454535027433 0ustar coucoufcoucouf/* * Copied from * https://codereview.qt-project.org/cat/29453%2C6%2Csrc/network/kernel/qnetworkproxy_libproxy.cpp%5E0 * * With minor modifications by * Alberto Mardegan */ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "my-network-proxy-factory.h" #include #include #include #include class QLibProxyWrapper { public: QLibProxyWrapper() : factory(px_proxy_factory_new()) { } ~QLibProxyWrapper() { px_proxy_factory_free(factory); } QList getProxies(const QUrl &url); private: pxProxyFactory *factory; }; Q_GLOBAL_STATIC(QLibProxyWrapper, libProxyWrapper); /* Gets the list of proxies from libproxy, converted to QUrl list. Thread safe, according to libproxy documentation. */ QList QLibProxyWrapper::getProxies(const QUrl &url) { QList ret; if (factory) { char **proxies = px_proxy_factory_get_proxies(factory, url.toEncoded()); if (proxies) { for (int i = 0; proxies[i]; i++) { ret.append(QUrl::fromEncoded(proxies[i])); free(proxies[i]); } free(proxies); } } return ret; } QList MyNetworkProxyFactory::queryProxy(const QNetworkProxyQuery &query) { QList proxyList; QUrl queryUrl; QNetworkProxy::Capabilities requiredCapabilities(0); switch (query.queryType()) { //URL requests are directly supported by libproxy case QNetworkProxyQuery::UrlRequest: queryUrl = query.url(); break; // fake URLs to get libproxy to tell us the SOCKS proxy case QNetworkProxyQuery::TcpSocket: queryUrl.setScheme(QLatin1String("tcp")); queryUrl.setHost(query.peerHostName()); queryUrl.setPort(query.peerPort()); requiredCapabilities |= QNetworkProxy::TunnelingCapability; break; case QNetworkProxyQuery::UdpSocket: queryUrl.setScheme(QLatin1String("udp")); queryUrl.setHost(query.peerHostName()); queryUrl.setPort(query.peerPort()); requiredCapabilities |= QNetworkProxy::UdpTunnelingCapability; break; default: proxyList.append(QNetworkProxy(QNetworkProxy::NoProxy)); return proxyList; } QList rawProxies = libProxyWrapper()->getProxies(queryUrl); bool haveDirectConnection = false; foreach (const QUrl& url, rawProxies) { QNetworkProxy::ProxyType type; if (url.scheme() == QLatin1String("http")) { type = QNetworkProxy::HttpProxy; } else if (url.scheme() == QLatin1String("socks") || url.scheme() == QLatin1String("socks5")) { type = QNetworkProxy::Socks5Proxy; } else if (url.scheme() == QLatin1String("ftp")) { type = QNetworkProxy::FtpCachingProxy; } else if (url.scheme() == QLatin1String("direct")) { type = QNetworkProxy::NoProxy; haveDirectConnection = true; } else { continue; //unsupported proxy type e.g. socks4 } QNetworkProxy proxy(type, url.host(), url.port(), url.userName(), url.password()); if ((proxy.capabilities() & requiredCapabilities) == requiredCapabilities) proxyList.append(proxy); } // fallback is direct connection if (proxyList.isEmpty() || !haveDirectConnection) proxyList.append(QNetworkProxy(QNetworkProxy::NoProxy)); return proxyList; } signond-nicolasfella/src/remotepluginprocess/my-network-proxy-factory.h0000664000175000017500000000230714615454535027072 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_MY_NETWORK_PROXY_FACTORY_H #define SIGNON_MY_NETWORK_PROXY_FACTORY_H #include class MyNetworkProxyFactory: public QNetworkProxyFactory { public: // reimplemented virtual methods QList queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery()); }; #endif // SIGNON_MY_NETWORK_PROXY_FACTORY_H signond-nicolasfella/src/remotepluginprocess/remotepluginprocess.cpp0000664000175000017500000002634714615454535026610 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include "debug.h" #ifdef HAVE_LIBPROXY #include "my-network-proxy-factory.h" #endif #include "remotepluginprocess.h" // signon-plugins-common #include "SignOn/blobiohandler.h" #include "SignOn/ipc.h" using namespace SignOn; namespace RemotePluginProcessNS { /* ---------------------- RemotePluginProcess ---------------------- */ RemotePluginProcess::RemotePluginProcess(QObject *parent): QObject(parent), m_currentOperation(PLUGIN_OP_STOP) { m_plugin = NULL; m_readnotifier = NULL; m_errnotifier = NULL; qRegisterMetaType("SignOn::SessionData"); qRegisterMetaType("QString"); } RemotePluginProcess::~RemotePluginProcess() { delete m_plugin; delete m_readnotifier; delete m_errnotifier; } RemotePluginProcess * RemotePluginProcess::createRemotePluginProcess(QString &type, QObject *parent) { RemotePluginProcess *rpp = new RemotePluginProcess(parent); //this is needed before plugin is initialized rpp->setupProxySettings(); if (!rpp->loadPlugin(type) || !rpp->setupDataStreams() || rpp->m_plugin->type() != type) { delete rpp; return NULL; } return rpp; } bool RemotePluginProcess::loadPlugin(QString &type) { TRACE() << " loading auth library for " << type; QLibrary lib(getPluginName(type)); if (!lib.load()) { qCritical() << QString("Failed to load %1 (reason: %2)") .arg(getPluginName(type)).arg(lib.errorString()); return false; } TRACE() << "library loaded"; typedef AuthPluginInterface* (*SsoAuthPluginInstanceF)(); SsoAuthPluginInstanceF instance = (SsoAuthPluginInstanceF)lib.resolve("auth_plugin_instance"); if (!instance) { qCritical() << QString("Failed to resolve init function in %1 " "(reason: %2)") .arg(getPluginName(type)).arg(lib.errorString()); return false; } TRACE() << "constructor resolved"; m_plugin = qobject_cast(instance()); if (!m_plugin) { qCritical() << QString("Failed to cast object for %1 type") .arg(type); return false; } connect(m_plugin, SIGNAL(result(const SignOn::SessionData&)), this, SLOT(result(const SignOn::SessionData&))); connect(m_plugin, SIGNAL(store(const SignOn::SessionData&)), this, SLOT(store(const SignOn::SessionData&))); connect(m_plugin, SIGNAL(error(const SignOn::Error &)), this, SLOT(error(const SignOn::Error &))); connect(m_plugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), this, SLOT(userActionRequired(const SignOn::UiSessionData&))); connect(m_plugin, SIGNAL(refreshed(const SignOn::UiSessionData&)), this, SLOT(refreshed(const SignOn::UiSessionData&))); connect(m_plugin, SIGNAL(statusChanged(const AuthPluginState, const QString&)), this, SLOT(statusChanged(const AuthPluginState, const QString&))); m_plugin->setParent(this); TRACE() << "plugin is fully initialized"; return true; } bool RemotePluginProcess::setupDataStreams() { TRACE(); m_inFile.open(STDIN_FILENO, QIODevice::ReadOnly); m_outFile.open(STDOUT_FILENO, QIODevice::WriteOnly); m_readnotifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read); m_errnotifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Exception); connect(m_readnotifier, SIGNAL(activated(int)), this, SLOT(startTask())); connect(m_errnotifier, SIGNAL(activated(int)), this, SIGNAL(processStopped())); m_blobIOHandler = new BlobIOHandler(&m_inFile, &m_outFile, this); connect(m_blobIOHandler, SIGNAL(dataReceived(const QVariantMap &)), this, SLOT(sessionDataReceived(const QVariantMap &))); connect(m_blobIOHandler, SIGNAL(error()), this, SLOT(blobIOError())); m_blobIOHandler->setReadChannelSocketNotifier(m_readnotifier); return true; } bool RemotePluginProcess::setupProxySettings() { TRACE(); #ifdef HAVE_LIBPROXY /* Use a libproxy-based proxy factory; this code will no longer be * needed when https://bugreports.qt-project.org/browse/QTBUG-26295 * is fixed. */ MyNetworkProxyFactory *proxyFactory = new MyNetworkProxyFactory(); QNetworkProxyFactory::setApplicationProxyFactory(proxyFactory); #endif return true; } void RemotePluginProcess::blobIOError() { error( Error(Error::InternalServer, QLatin1String("Failed to I/O session data to/from the signon daemon."))); } void RemotePluginProcess::result(const SignOn::SessionData &data) { QDataStream out(&m_outFile); QVariantMap resultDataMap; foreach(QString key, data.propertyNames()) resultDataMap[key] = data.getProperty(key); out << (quint32)PLUGIN_RESPONSE_RESULT; m_blobIOHandler->sendData(resultDataMap); m_outFile.flush(); } void RemotePluginProcess::store(const SignOn::SessionData &data) { QDataStream out(&m_outFile); QVariantMap storeDataMap; foreach(QString key, data.propertyNames()) storeDataMap[key] = data.getProperty(key); out << (quint32)PLUGIN_RESPONSE_STORE; m_blobIOHandler->sendData(storeDataMap); m_outFile.flush(); } void RemotePluginProcess::error(const SignOn::Error &err) { QDataStream out(&m_outFile); out << (quint32)PLUGIN_RESPONSE_ERROR; out << (quint32)err.type(); out << err.message(); m_outFile.flush(); TRACE() << "error is sent" << err.type() << " " << err.message(); } void RemotePluginProcess::userActionRequired(const SignOn::UiSessionData &data) { TRACE(); QDataStream out(&m_outFile); QVariantMap resultDataMap; foreach(QString key, data.propertyNames()) resultDataMap[key] = data.getProperty(key); out << (quint32)PLUGIN_RESPONSE_UI; m_blobIOHandler->sendData(resultDataMap); m_outFile.flush(); } void RemotePluginProcess::refreshed(const SignOn::UiSessionData &data) { TRACE(); QDataStream out(&m_outFile); QVariantMap resultDataMap; foreach(QString key, data.propertyNames()) resultDataMap[key] = data.getProperty(key); out << (quint32)PLUGIN_RESPONSE_REFRESHED; m_blobIOHandler->sendData(resultDataMap); m_outFile.flush(); } void RemotePluginProcess::statusChanged(const AuthPluginState state, const QString &message) { TRACE(); QDataStream out(&m_outFile); out << (quint32)PLUGIN_RESPONSE_SIGNAL; out << (quint32)state; out << message; m_outFile.flush(); } QString RemotePluginProcess::getPluginName(const QString &type) { QString dirName = qgetenv("SSO_PLUGINS_DIR"); if (dirName.isEmpty()) dirName = QDir::cleanPath(SIGNOND_PLUGINS_DIR); QString fileName = dirName + QDir::separator() + QString(SIGNON_PLUGIN_PREFIX) + type + QString(SIGNON_PLUGIN_SUFFIX); return fileName; } void RemotePluginProcess::type() { QDataStream out(&m_outFile); out << m_plugin->type(); } void RemotePluginProcess::mechanisms() { QDataStream out(&m_outFile); QStringList mechanisms = m_plugin->mechanisms(); QVariant mechsVar = mechanisms; out << mechsVar; } void RemotePluginProcess::process() { QDataStream in(&m_inFile); in >> m_currentMechanism; int processBlobSize = -1; in >> processBlobSize; m_currentOperation = PLUGIN_OP_PROCESS; m_blobIOHandler->receiveData(processBlobSize); } void RemotePluginProcess::userActionFinished() { QDataStream in(&m_inFile); int processBlobSize = -1; in >> processBlobSize; m_currentOperation = PLUGIN_OP_PROCESS_UI; m_blobIOHandler->receiveData(processBlobSize); } void RemotePluginProcess::refresh() { QDataStream in(&m_inFile); int processBlobSize = -1; in >> processBlobSize; m_currentOperation = PLUGIN_OP_REFRESH; m_blobIOHandler->receiveData(processBlobSize); } void RemotePluginProcess::sessionDataReceived(const QVariantMap &sessionDataMap) { if (m_currentOperation == PLUGIN_OP_PROCESS) { SessionData inData(sessionDataMap); m_plugin->process(inData, m_currentMechanism); m_currentMechanism.clear(); } else if(m_currentOperation == PLUGIN_OP_PROCESS_UI) { UiSessionData inData(sessionDataMap); m_plugin->userActionFinished(inData); } else if(m_currentOperation == PLUGIN_OP_REFRESH) { UiSessionData inData(sessionDataMap); m_plugin->refresh(inData); } else { TRACE() << "Wrong operation code."; error(Error(Error::InternalServer, QLatin1String("Plugin process - invalid operation code."))); } m_currentOperation = PLUGIN_OP_STOP; } void RemotePluginProcess::startTask() { if (m_blobIOHandler->isReading()) { /* A data blob is being read; there's nothing for us here */ return; } quint32 opcode = PLUGIN_OP_STOP; bool is_stopped = false; QDataStream in(&m_inFile); in >> opcode; /* If the plugin is busy, the only allowed action here is canceling */ if (m_currentOperation != PLUGIN_OP_STOP && opcode != PLUGIN_OP_CANCEL) { qCritical() << "Operation requested while plugin busy! - code" << opcode; m_plugin->abort(); Q_EMIT processStopped(); return; } switch (opcode) { case PLUGIN_OP_CANCEL: m_plugin->cancel(); break; case PLUGIN_OP_TYPE: type(); break; case PLUGIN_OP_MECHANISMS: mechanisms(); break; case PLUGIN_OP_PROCESS: process(); break; case PLUGIN_OP_PROCESS_UI: userActionFinished(); break; case PLUGIN_OP_REFRESH: refresh(); break; case PLUGIN_OP_STOP: is_stopped = true; break; default: { qCritical() << " unknown operation code: " << opcode; is_stopped = true; } break; }; TRACE() << "operation is completed"; if (!is_stopped) { if (!m_outFile.flush()) is_stopped = true; } if (is_stopped) { m_plugin->abort(); emit processStopped(); } } } //namespace RemotePluginProcessNS signond-nicolasfella/src/remotepluginprocess/remotepluginprocess.h0000664000175000017500000000630214615454535026242 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef REMOTEPLUGINPROCESS_H #define REMOTEPLUGINPROCESS_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "SignOn/uisessiondata.h" #include "SignOn/authpluginif.h" extern "C" { #include #include #include } #ifndef SIGNOND_PLUGINS_DIR #define SIGNOND_PLUGINS_DIR "/usr/lib/signon" #endif #ifndef SIGNON_PLUGIN_PREFIX #define SIGNON_PLUGIN_PREFIX "lib" #endif #ifndef SIGNON_PLUGIN_SUFFIX #define SIGNON_PLUGIN_SUFFIX "plugin.so" #endif using namespace SignOn; namespace SignOn { class BlobIOHandler; }; namespace RemotePluginProcessNS { /*! * @class RemotePluginProcess * Class to execute plugin process. */ class RemotePluginProcess: public QObject { Q_OBJECT public: RemotePluginProcess(QObject *parent); ~RemotePluginProcess(); static RemotePluginProcess* createRemotePluginProcess(QString &type, QObject *parent); bool loadPlugin(QString &type); bool setupDataStreams(); bool setupProxySettings(); public Q_SLOTS: void startTask(); void sessionDataReceived(const QVariantMap &sessionDataMap); private: AuthPluginInterface *m_plugin; QFile m_inFile; QFile m_outFile; QSocketNotifier *m_readnotifier; QSocketNotifier *m_errnotifier; BlobIOHandler *m_blobIOHandler; //Requiered for async session data reading quint32 m_currentOperation; QString m_currentMechanism; private: QString getPluginName(const QString &type); void type(); void mechanism(); void mechanisms(); void process(); void userActionFinished(); void refresh(); private Q_SLOTS: void result(const SignOn::SessionData &data); void store(const SignOn::SessionData &data); void error(const SignOn::Error &err); void userActionRequired(const SignOn::UiSessionData &data); void refreshed(const SignOn::UiSessionData &data); void statusChanged(const AuthPluginState state, const QString &message); void blobIOError(); Q_SIGNALS : void processStopped(); }; } //namespace RemotePluginProcessNS #endif /* REMOTEPLUGINPROCESS_H */ signond-nicolasfella/src/remotepluginprocess/remotepluginprocess.pro0000664000175000017500000000210314615454535026606 0ustar coucoufcoucoufinclude( ../../common-project-config.pri ) include( ../../common-vars.pri ) TEMPLATE = app TARGET = signonpluginprocess QT += core network QT -= gui HEADERS += \ debug.h \ remotepluginprocess.h SOURCES += \ debug.cpp \ main.cpp \ remotepluginprocess.cpp INCLUDEPATH += . \ $$TOP_SRC_DIR/src \ $$TOP_SRC_DIR/src/plugins \ $$TOP_SRC_DIR/src/signond \ $$TOP_SRC_DIR/lib/plugins/signon-plugins-common \ $$TOP_SRC_DIR/lib/plugins \ $$TOP_SRC_DIR/lib CONFIG += \ build_all lessThan(QT_VERSION, "5.5.0"):system($$pkgConfigExecutable() --exists libproxy-1.0) { DEFINES += HAVE_LIBPROXY PKGCONFIG += libproxy-1.0 SOURCES += my-network-proxy-factory.cpp } QMAKE_LIBDIR += \ $${TOP_BUILD_DIR}/lib/plugins/signon-plugins-common \ $${TOP_BUILD_DIR}/lib/plugins LIBS += \ -lsignon-plugins-common \ -lsignon-plugins DEFINES += SIGNON_PLUGIN_TRACE DEFINES += "SIGNOND_PLUGINS_DIR=$${SIGNOND_PLUGINS_DIR_QUOTED}" include( ../../common-installs-config.pri ) signond-nicolasfella/src/signond/0000775000175000017500000000000014615454547017312 5ustar coucoufcoucoufsignond-nicolasfella/src/signond/accesscontrolmanagerhelper.cpp0000664000175000017500000001504314615454535025413 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * Contact: Elena Reshetova * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #ifdef ENABLE_P2P #include #endif #include "accesscontrolmanagerhelper.h" #include "signond-common.h" #include "credentialsaccessmanager.h" #include "signonidentity.h" using namespace SignonDaemonNS; AccessControlManagerHelper *AccessControlManagerHelper::m_pInstance = NULL; AccessControlManagerHelper *AccessControlManagerHelper::instance() { return m_pInstance; } AccessControlManagerHelper::AccessControlManagerHelper( SignOn::AbstractAccessControlManager *acManager) { if (!m_pInstance) { m_pInstance = this; m_acManager = acManager; } else { BLAME() << "Creating a second instance of the CAM"; } } AccessControlManagerHelper::~AccessControlManagerHelper() { m_acManager = NULL; m_pInstance = NULL; } bool AccessControlManagerHelper::isPeerAllowedToUseIdentity( const PeerContext &peerContext, const quint32 identityId) { // TODO - improve this, the error handling and more precise behaviour CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if (db == 0) { TRACE() << "NULL db pointer, secure storage might be unavailable,"; return false; } QStringList acl = db->accessControlList(identityId); TRACE() << QString(QLatin1String("Access control list of identity: " "%1: [%2].Tokens count: %3\t")) .arg(identityId) .arg(acl.join(QLatin1String(", "))) .arg(acl.size()); if (db->errorOccurred()) return false; IdentityOwnership ownership = isPeerOwnerOfIdentity(peerContext, identityId); if (ownership == ApplicationIsOwner) return true; if (acl.isEmpty()) return false; if (acl.contains(QLatin1String("*"))) return true; return peerHasOneOfAccesses(peerContext, acl); } AccessControlManagerHelper::IdentityOwnership AccessControlManagerHelper::isPeerOwnerOfIdentity( const PeerContext &peerContext, const quint32 identityId) { CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if (db == 0) { TRACE() << "NULL db pointer, secure storage might be unavailable,"; return ApplicationIsNotOwner; } QStringList ownerSecContexts = db->ownerList(identityId); if (db->errorOccurred()) return ApplicationIsNotOwner; if (ownerSecContexts.isEmpty()) return IdentityDoesNotHaveOwner; return peerHasOneOfAccesses(peerContext, ownerSecContexts) ? ApplicationIsOwner : ApplicationIsNotOwner; } bool AccessControlManagerHelper::isPeerKeychainWidget( const PeerContext &peerContext) { static QString keychainWidgetAppId = m_acManager->keychainWidgetAppId(); QString peerAppId = appIdOfPeer(peerContext); return (peerAppId == keychainWidgetAppId); } QString AccessControlManagerHelper::appIdOfPeer( const PeerContext &peerContext) { TRACE() << m_acManager->appIdOfPeer(peerContext.connection(), peerContext.message()); return m_acManager->appIdOfPeer(peerContext.connection(), peerContext.message()); } bool AccessControlManagerHelper::peerHasOneOfAccesses( const PeerContext &peerContext, const QStringList secContexts) { foreach(QString securityContext, secContexts) { TRACE() << securityContext; if (isPeerAllowedToAccess(peerContext, securityContext)) return true; } BLAME() << "given peer does not have needed permissions"; return false; } bool AccessControlManagerHelper::isPeerAllowedToAccess( const PeerContext &peerContext, const QString securityContext) { TRACE() << securityContext; return m_acManager->isPeerAllowedToAccess(peerContext.connection(), peerContext.message(), securityContext); } pid_t AccessControlManagerHelper::pidOfPeer(const PeerContext &peerContext) { QString service = peerContext.message().service(); if (service.isEmpty()) { #ifdef ENABLE_P2P DBusConnection *connection = (DBusConnection *)peerContext.connection().internalPointer(); unsigned long pid = 0; dbus_bool_t ok = dbus_connection_get_unix_process_id(connection, &pid); if (Q_UNLIKELY(!ok)) { BLAME() << "Couldn't get PID of caller!"; return 0; } return pid; #else BLAME() << "Empty caller name, and no P2P support enabled"; return 0; #endif } else { return peerContext.connection().interface()->servicePid(service).value(); } } SignOn::AccessReply * AccessControlManagerHelper::requestAccessToIdentity( const PeerContext &peerContext, quint32 id) { SignOn::AccessRequest request; request.setPeer(peerContext.connection(), peerContext.message()); request.setIdentity(id); return m_acManager->handleRequest(request); } signond-nicolasfella/src/signond/accesscontrolmanagerhelper.h0000664000175000017500000001463014615454535025061 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * Contact: Elena Reshetova * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! @file accesscontrolmanagerhelper.h Helper class for access control-related functionality @ingroup Accounts_and_SSO_Framework */ #ifndef ACCESSCONTROLMANAGERHELPER_H #define ACCESSCONTROLMANAGERHELPER_H #include "peercontext.h" #include "signonauthsession.h" #include "SignOn/abstract-access-control-manager.h" namespace SignonDaemonNS { /*! * @class AccessControlManagerHelper * Contains helper functions related to Access Control * @ingroup Accounts_and_SSO_Framework */ class AccessControlManagerHelper { public: /*! * @enum IdentityOwnership * Specifies the owner relationship of an application over a specific * identity, or the lack of ownership over that specific identity. * @see isPeerOwnerOfIdentity(). */ enum IdentityOwnership { ApplicationIsOwner = 0, ApplicationIsNotOwner, IdentityDoesNotHaveOwner }; AccessControlManagerHelper(SignOn::AbstractAccessControlManager *acManager); ~AccessControlManagerHelper(); /*! * @param peerContext, the context, which process id we want to know * @returns process id of service client. */ static pid_t pidOfPeer(const PeerContext &peerContext); /* creating an instance of a class */ static AccessControlManagerHelper *instance(); /*! * Checks if a client process is allowed to use a specific SignonIdentity. * @param peerContext the peer connection over which the message was sent. * @param identityId, the SignonIdentity to be used. * @returns true, if the peer is allowed, false otherwise. */ bool isPeerAllowedToUseIdentity(const PeerContext &peerContext, const quint32 identityId); /*! * Checks if a specific process is the owner of a SignonIdentity, thus * having full control over it. * @param peerContext the peer connection over which the message was sent. * @param identityId, the SignonIdentity in context. * @retval ApplicationIsOwner/ApplicationIsNotOwner if the identity * is/isn't the owner or IdentityDoesNotHaveOwner if the identity does not * have an owner at all. */ IdentityOwnership isPeerOwnerOfIdentity(const PeerContext &peerContext, const quint32 identityId); /*! * Checks if a specific process is allowed to use the SignonAuthSession * functionality. * @param peerContext the peer connection over which the message was sent. * @param authSession, the authentication session to be used by the peer * request. * @returns true, if the peer is allowed, false otherwise. */ bool isPeerAllowedToUseAuthSession(const PeerContext &peerContext, const SignonAuthSession &authSession) { return isPeerAllowedToUseIdentity(peerContext, authSession.id()); } /*! * Checks if a specific process is allowed to use the SignonAuthSession * functionality. * @param peerContext the peer connection over which the message was sent. * @param ownerIdentityId, id of the Identity owning the authentication * session. * @returns true, if the peer is allowed, false otherwise. */ bool isPeerAllowedToUseAuthSession(const PeerContext &peerContext, const quint32 ownerIdentityId) { return isPeerAllowedToUseIdentity(peerContext, ownerIdentityId); } /*! * @param peerContext the peer connection over which the message was sent. * @returns true, if the peer is the Keychain Widget, false otherwise. */ bool isPeerKeychainWidget(const PeerContext &peerContext); /*! * Looks up for the application identifier of a specific client process. * @param peerContext the peer connection over which the message was sent. * @returns the application identifier of the process, or an empty string * if none found. */ QString appIdOfPeer(const PeerContext &peerContext); /*! * Checks if a client process is allowed to access objects with a certain * security context. * The access type to be checked depends on the concrete implementation of * this function. * @param peerContext the peer connection over which the message was sent. * @param securityContext, the securityContext to be checked against. * @returns true, if the peer is allowed, false otherwise. */ bool isPeerAllowedToAccess(const PeerContext &peerContext, const QString securityContext); /*! * Checks if a client process is allowed to access at least one object from * the list with a certain security context. * The access type to be checked depends on the concrete implementation of * this function. * @param peerContext the peer connection over which the message was sent. * @param secContexts, the objects' securityContexts to be checked against. * @returns true, if the peer is allowed, false otherwise. */ bool peerHasOneOfAccesses(const PeerContext &peerContext, const QStringList secContexts); SignOn::AccessReply * requestAccessToIdentity(const PeerContext &peerContext, quint32 id); private: SignOn::AbstractAccessControlManager *m_acManager; static AccessControlManagerHelper* m_pInstance; }; } // namespace SignonDaemonNS #endif // ACCESSCONTROLMANAGER_H signond-nicolasfella/src/signond/backup.cpp0000664000175000017500000002262314615454535021265 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include "SignOn/misc.h" #include "backup.h" #include "backup_adaptor.h" #include "credentialsaccessmanager.h" #include "signond-common.h" #define BACKUP_DIR_NAME() \ (QDir::separator() + QLatin1String("backup")) using namespace SignOn; namespace SignonDaemonNS { Backup::Backup(CredentialsAccessManager *cam, bool backupMode, QObject *parent): QObject(parent), m_cam(cam), m_backup(backupMode) { QDBusConnection sessionConnection = QDBusConnection::sessionBus(); QDBusConnection::RegisterOptions registerSessionOptions = QDBusConnection::ExportAdaptors; (void)new BackupclientAdaptor(this); if (!sessionConnection.registerObject(SIGNOND_DAEMON_OBJECTPATH + QLatin1String("/Backup"), this, registerSessionOptions)) { TRACE() << "Object cannot be registered"; qFatal("SignonDaemon requires to register backup object"); } if (!sessionConnection.registerService(SIGNOND_SERVICE + QLatin1String(".Backup"))) { QDBusError err = sessionConnection.lastError(); TRACE() << "Service cannot be registered: " << err.errorString(err.type()); qFatal("SignonDaemon requires to register backup service"); } } Backup::~Backup() { QDBusConnection sessionConnection = QDBusConnection::sessionBus(); sessionConnection.unregisterObject(SIGNOND_DAEMON_OBJECTPATH + QLatin1String("/Backup")); sessionConnection.unregisterService(SIGNOND_SERVICE + QLatin1String(".Backup")); } void Backup::eraseBackupDir() const { const CAMConfiguration &config = m_cam->configuration(); QString backupRoot = config.m_storagePath + BACKUP_DIR_NAME(); QDir target(backupRoot); if (!target.exists()) return; QStringList targetEntries = target.entryList(QDir::Files); foreach (QString entry, targetEntries) { target.remove(entry); } target.rmdir(backupRoot); } bool Backup::copyToBackupDir(const QStringList &fileNames) const { const CAMConfiguration &config = m_cam->configuration(); QString backupRoot = config.m_storagePath + BACKUP_DIR_NAME(); QDir target(backupRoot); if (!target.exists() && !target.mkpath(backupRoot)) { qCritical() << "Cannot create target directory"; return false; } setUserOwnership(backupRoot); /* Now copy the files to be backed up */ bool ok = true; foreach (const QString &fileName, fileNames) { /* Remove the target file, if it exists */ if (target.exists(fileName)) target.remove(fileName); /* Copy the source into the target directory */ QString source = config.m_storagePath + QDir::separator() + fileName; if (!QFile::exists(source)) continue; QString destination = backupRoot + QDir::separator() + fileName; ok = QFile::copy(source, destination); if (!ok) { BLAME() << "Copying" << source << "to" << destination << "failed"; break; } setUserOwnership(destination); } return ok; } bool Backup::copyFromBackupDir(const QStringList &fileNames) const { const CAMConfiguration &config = m_cam->configuration(); QString backupRoot = config.m_storagePath + BACKUP_DIR_NAME(); QDir sourceDir(backupRoot); if (!sourceDir.exists()) { TRACE() << "Backup directory does not exist!"; } if (!sourceDir.exists(config.m_dbName)) { TRACE() << "Backup does not contain DB:" << config.m_dbName; } /* Now restore the files from the backup */ bool ok = true; QDir target(config.m_storagePath); QStringList movedFiles, copiedFiles; foreach (const QString &fileName, fileNames) { /* Rename the target file, if it exists */ if (target.exists(fileName)) { if (target.rename(fileName, fileName + QLatin1String(".bak"))) movedFiles += fileName; } /* Copy the source into the target directory */ QString source = backupRoot + QDir::separator() + fileName; if (!QFile::exists(source)) { TRACE() << "Ignoring file not present in backup:" << source; continue; } QString destination = config.m_storagePath + QDir::separator() + fileName; ok = QFile::copy(source, destination); if (ok) { copiedFiles << fileName; } else { qWarning() << "Copy failed for:" << source; break; } } if (!ok) { qWarning() << "Restore failed, recovering previous DB"; foreach (const QString &fileName, copiedFiles) { target.remove(fileName); } foreach (const QString &fileName, movedFiles) { if (!target.rename(fileName + QLatin1String(".bak"), fileName)) { qCritical() << "Could not recover:" << fileName; } } } else { /* delete ".bak" files */ foreach (const QString &fileName, movedFiles) { target.remove(fileName + QLatin1String(".bak")); } } return ok; } bool Backup::createStorageFileTree(const QStringList &backupFiles) const { const CAMConfiguration &config = m_cam->configuration(); QDir storageDir(config.m_storagePath); if (!storageDir.exists()) { if (!storageDir.mkpath(config.m_storagePath)) { qCritical() << "Could not create storage dir for backup."; return false; } } foreach (const QString &fileName, backupFiles) { if (storageDir.exists(fileName)) continue; QString filePath = storageDir.path() + QDir::separator() + fileName; QFile file(filePath); if (!file.open(QIODevice::WriteOnly)) { qCritical() << "Failed to create empty file for backup:" << filePath; return false; } else { file.close(); } } return true; } uchar Backup::backupStarts() { TRACE() << "backup"; if (!m_backup && m_cam->credentialsSystemOpened()) { m_cam->closeCredentialsSystem(); if (m_cam->credentialsSystemOpened()) { qCritical() << "Cannot close credentials database"; return 2; } } const CAMConfiguration &config = m_cam->configuration(); /* do backup copy: prepare the list of files to be backed up */ QStringList backupFiles; backupFiles << config.m_dbName; backupFiles << m_cam->backupFiles(); /* make sure that all the backup files and storage directory exist: create storage dir and empty files if not so, as backup/restore operations must be consistent */ if (!createStorageFileTree(backupFiles)) { qCritical() << "Cannot create backup file tree."; return 2; } /* perform the copy */ eraseBackupDir(); if (!copyToBackupDir(backupFiles)) { qCritical() << "Cannot copy database"; if (!m_backup) m_cam->openCredentialsSystem(); return 2; } if (!m_backup) { //mount file system back if (!m_cam->openCredentialsSystem()) { qCritical() << "Cannot reopen database"; } } return 0; } uchar Backup::backupFinished() { TRACE() << "close"; eraseBackupDir(); if (m_backup) { //close daemon TRACE() << "close daemon"; QCoreApplication::quit(); } return 0; } /* * Does nothing but start-on-demand * */ uchar Backup::restoreStarts() { TRACE(); return 0; } uchar Backup::restoreFinished() { TRACE() << "restore"; //restore requested if (m_cam->credentialsSystemOpened()) { //umount file system if (!m_cam->closeCredentialsSystem()) { qCritical() << "database cannot be closed"; return 2; } } const CAMConfiguration &config = m_cam->configuration(); QStringList backupFiles; backupFiles << config.m_dbName; backupFiles << m_cam->backupFiles(); /* perform the copy */ if (!copyFromBackupDir(backupFiles)) { qCritical() << "Cannot copy database"; m_cam->openCredentialsSystem(); return 2; } eraseBackupDir(); //TODO check database integrity if (!m_backup) { //mount file system back if (!m_cam->openCredentialsSystem()) return 2; } return 0; } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/backup.h0000664000175000017500000000334214615454535020727 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_BACKUP_H_ #define SIGNON_BACKUP_H_ #include #include #include namespace SignonDaemonNS { class CredentialsAccessManager; class Backup: public QObject, protected QDBusContext { Q_OBJECT public: Backup(CredentialsAccessManager *cam, bool backupMode, QObject *parent = 0); ~Backup(); public Q_SLOTS: uchar backupStarts(); uchar backupFinished(); uchar restoreStarts(); uchar restoreFinished(); private: void eraseBackupDir() const; bool copyToBackupDir(const QStringList &fileNames) const; bool copyFromBackupDir(const QStringList &fileNames) const; bool createStorageFileTree(const QStringList &fileNames) const; private: CredentialsAccessManager *m_cam; bool m_backup; // whether signond was started just to take a backup }; } // namespace #endif /* SIGNON_BACKUP_H_ */ signond-nicolasfella/src/signond/credentialsaccessmanager.cpp0000664000175000017500000005060414615454535025032 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #define SIGNON_ENABLE_UNSTABLE_APIS #include "credentialsaccessmanager.h" #include "default-crypto-manager.h" #include "default-key-authorizer.h" #include "default-secrets-storage.h" #include "signond-common.h" #include "SignOn/ExtensionInterface" #include "SignOn/misc.h" #include #include #define RETURN_IF_NOT_INITIALIZED(return_value) \ do { \ if (!m_isInitialized) { \ m_error = NotInitialized; \ TRACE() << "CredentialsAccessManager not initialized."; \ return return_value; \ } \ } while (0) using namespace SignonDaemonNS; using namespace SignOn; /* ---------------------- CAMConfiguration ---------------------- */ CAMConfiguration::CAMConfiguration(): m_dbName(QLatin1String(signonDefaultDbName)), m_secretsDbName(QLatin1String(signonDefaultSecretsDbName)), m_encryptionPassphrase(QByteArray()) { setStoragePath(QLatin1String(signonDefaultStoragePath)); } void CAMConfiguration::serialize(QIODevice *device) { if (device == NULL) return; if (!device->open(QIODevice::ReadWrite)) { return; } QString buffer; QTextStream stream(&buffer); stream << "\n\n====== Credentials Access Manager Configuration ======\n\n"; const char *usingEncryption = useEncryption() ? "true" : "false"; stream << "Using encryption: " << usingEncryption << '\n'; stream << "Metadata DB path: " << metadataDBPath() << '\n'; stream << "Cryptomanager name: " << cryptoManagerName() << '\n'; stream << "ACL manager name: " << accessControlManagerName() << '\n'; stream << "Secrets storage name: " << secretsStorageName() << '\n'; stream << "======================================================\n\n"; device->write(buffer.toUtf8()); device->close(); } QString CAMConfiguration::metadataDBPath() const { return m_storagePath + QDir::separator() + m_dbName; } QString CAMConfiguration::cryptoManagerName() const { return m_settings.value(QLatin1String("CryptoManager")).toString(); } QString CAMConfiguration::accessControlManagerName() const { return m_settings.value(QLatin1String("AccessControlManager")).toString(); } bool CAMConfiguration::useEncryption() const { return cryptoManagerName() != QLatin1String("default"); } QString CAMConfiguration::secretsStorageName() const { return m_settings.value(QLatin1String("SecretsStorage")).toString(); } void CAMConfiguration::setStoragePath(const QString &storagePath) { m_storagePath = storagePath; if (m_storagePath.startsWith(QLatin1Char('~'))) m_storagePath.replace(0, 1, QDir::homePath()); // CryptoSetup extensions are given the m_settings dictionary only addSetting(QLatin1String("StoragePath"), m_storagePath); } /* ---------------------- CredentialsAccessManager ---------------------- */ CredentialsAccessManager *CredentialsAccessManager::m_pInstance = NULL; CredentialsAccessManager::CredentialsAccessManager( const CAMConfiguration &configuration, QObject *parent): QObject(parent), m_isInitialized(false), m_systemOpened(false), m_error(NoError), keyManagers(), m_pCredentialsDB(NULL), m_cryptoManager(NULL), m_keyHandler(NULL), m_keyAuthorizer(NULL), m_secretsStorage(NULL), m_CAMConfiguration(configuration), m_acManager(NULL), m_acManagerHelper(NULL) { if (!m_pInstance) { m_pInstance = this; } else { BLAME() << "Creating a second instance of the CAM"; } m_keyHandler = new SignOn::KeyHandler(this); } CredentialsAccessManager::~CredentialsAccessManager() { closeCredentialsSystem(); m_pInstance = NULL; } CredentialsAccessManager *CredentialsAccessManager::instance() { return m_pInstance; } void CredentialsAccessManager::finalize() { TRACE() << "Enter"; if (m_systemOpened) closeCredentialsSystem(); // Disconnect all key managers foreach (SignOn::AbstractKeyManager *keyManager, keyManagers) keyManager->disconnect(); m_isInitialized = false; m_error = NoError; } bool CredentialsAccessManager::init() { if (m_isInitialized) { TRACE() << "CAM already initialized."; m_error = AlreadyInitialized; return false; } QBuffer config; m_CAMConfiguration.serialize(&config); TRACE() << "Initializing CredentialsAccessManager with configuration: " << config.data(); if (!createStorageDir()) { BLAME() << "Failed to create storage directory."; return false; } if (m_secretsStorage == 0) { QString name = m_CAMConfiguration.secretsStorageName(); if (!name.isEmpty() && name != QLatin1String("default")) { BLAME() << "Couldn't load SecretsStorage:" << name; } TRACE() << "No SecretsStorage set, using default (dummy)"; m_secretsStorage = new DefaultSecretsStorage(this); } //Initialize AccessControlManager if (m_acManager == 0) { QString name = m_CAMConfiguration.accessControlManagerName(); if (!name.isEmpty() && name != QLatin1String("default")) { BLAME() << "Couldn't load AccessControlManager:" << name; } TRACE() << "No AccessControlManager set, using default (dummy)"; m_acManager = new SignOn::AbstractAccessControlManager(this); } //Initialize AccessControlManagerHelper if (m_acManagerHelper == 0) { m_acManagerHelper = new AccessControlManagerHelper(m_acManager); } //Initialize CryptoManager if (m_cryptoManager == 0) { QString name = m_CAMConfiguration.cryptoManagerName(); if (!name.isEmpty() && name != QLatin1String("default")) { BLAME() << "Couldn't load CryptoManager:" << name; } TRACE() << "No CryptoManager set, using default (dummy)"; m_cryptoManager = new DefaultCryptoManager(this); } QObject::connect(m_cryptoManager, SIGNAL(fileSystemMounted()), this, SLOT(onEncryptedFSMounted())); QObject::connect(m_cryptoManager, SIGNAL(fileSystemUnmounting()), this, SLOT(onEncryptedFSUnmounting())); m_cryptoManager->initialize(m_CAMConfiguration.m_settings); /* This check is an optimization: instantiating the KeyAuthorizer is * probably not harmful if useEncryption() is false, but it's certainly * useless. */ if (m_CAMConfiguration.useEncryption()) { if (m_keyAuthorizer == 0) { TRACE() << "No key authorizer set, using default"; m_keyAuthorizer = new DefaultKeyAuthorizer(m_keyHandler, this); } QObject::connect(m_keyAuthorizer, SIGNAL(keyAuthorizationQueried(const SignOn::Key,int)), this, SLOT(onKeyAuthorizationQueried(const SignOn::Key,int))); /* These signal connections should be done after instantiating the * KeyAuthorizer, so that the KeyAuthorizer's slot will be called * first (or we could connect to them in queued mode) */ QObject::connect(m_keyHandler, SIGNAL(ready()), this, SIGNAL(credentialsSystemReady())); QObject::connect(m_keyHandler, SIGNAL(keyInserted(SignOn::Key)), this, SLOT(onKeyInserted(SignOn::Key))); QObject::connect(m_keyHandler, SIGNAL(lastAuthorizedKeyRemoved(SignOn::Key)), this, SLOT(onLastAuthorizedKeyRemoved(SignOn::Key))); QObject::connect(m_keyHandler, SIGNAL(keyRemoved(SignOn::Key)), this, SLOT(onKeyRemoved(SignOn::Key))); m_keyHandler->initialize(m_cryptoManager, keyManagers); } m_isInitialized = true; m_error = NoError; TRACE() << "CredentialsAccessManager successfully initialized..."; return true; } void CredentialsAccessManager::addKeyManager( SignOn::AbstractKeyManager *keyManager) { keyManagers.append(keyManager); } bool CredentialsAccessManager::initExtension(QObject *plugin) { bool extensionInUse = false; SignOn::ExtensionInterface *extension; SignOn::ExtensionInterface2 *extension2; SignOn::ExtensionInterface3 *extension3; extension3 = qobject_cast(plugin); if (extension3 != 0) extension2 = extension3; else extension2 = qobject_cast(plugin); if (extension2 != 0) extension = extension2; else extension = qobject_cast(plugin); if (extension == 0) { qWarning() << "Plugin instance is not an ExtensionInterface"; return false; } SignOn::AbstractKeyManager *keyManager = extension->keyManager(this); if (keyManager) { addKeyManager(keyManager); extensionInUse = true; } /* Check if the extension implements the new interface and provides a key * authorizer. */ if (extension2 != 0) { SignOn::AbstractKeyAuthorizer *keyAuthorizer = extension2->keyAuthorizer(m_keyHandler, this); if (keyAuthorizer != 0) { if (m_keyAuthorizer == 0) { m_keyAuthorizer = keyAuthorizer; extensionInUse = true; } else { TRACE() << "Key authorizer already set"; delete keyAuthorizer; } } } if (extension3 != 0) { /* Instantiate this plugin's CryptoManager only if it's the plugin * requested in the config file. */ if (m_CAMConfiguration.cryptoManagerName().isEmpty() || plugin->objectName() == m_CAMConfiguration.cryptoManagerName()) { SignOn::AbstractCryptoManager *cryptoManager = extension3->cryptoManager(this); if (cryptoManager != 0) { if (m_cryptoManager == 0) { m_cryptoManager = cryptoManager; extensionInUse = true; } else { TRACE() << "Crypto manager already set"; delete cryptoManager; } } } if (m_CAMConfiguration.secretsStorageName().isEmpty() || plugin->objectName() == m_CAMConfiguration.secretsStorageName()) { SignOn::AbstractSecretsStorage *secretsStorage = extension3->secretsStorage(this); if (secretsStorage != 0) { if (m_secretsStorage == 0) { m_secretsStorage = secretsStorage; extensionInUse = true; } else { TRACE() << "SecretsStorage already set"; delete secretsStorage; } } } /* Instantiate this plugin's AccessControlManager only if it's the * plugin requested in the config file. */ if (m_CAMConfiguration.accessControlManagerName().isEmpty() || plugin->objectName() == m_CAMConfiguration.accessControlManagerName()) { SignOn::AbstractAccessControlManager *acManager = extension3->accessControlManager(this); if (acManager != 0) { if (m_acManager == 0) { m_acManager = acManager; extensionInUse = true; } else { TRACE() << "Access control manager already set"; delete acManager; } } } } return extensionInUse; } QStringList CredentialsAccessManager::backupFiles() const { QStringList files; files << m_cryptoManager->backupFiles(); return files; } bool CredentialsAccessManager::openSecretsDB() { if (!m_cryptoManager->fileSystemIsMounted()) { /* Do not attempt to mount the FS; we know that it will be mounted * automatically, as soon as some encryption keys are provided */ m_error = CredentialsDbNotMounted; return false; } QString dbPath = m_cryptoManager->fileSystemMountPath() + QDir::separator() + m_CAMConfiguration.m_secretsDbName; TRACE() << "Database name: [" << dbPath << "]"; if (!m_pCredentialsDB->openSecretsDB(dbPath)) return false; m_error = NoError; return true; } bool CredentialsAccessManager::isSecretsDBOpen() { return m_pCredentialsDB->isSecretsDBOpen(); } bool CredentialsAccessManager::closeSecretsDB() { m_pCredentialsDB->closeSecretsDB(); if (!m_cryptoManager->unmountFileSystem()) { m_error = CredentialsDbUnmountFailed; return false; } return true; } bool CredentialsAccessManager::createStorageDir() { QString dbPath = m_CAMConfiguration.metadataDBPath(); QFileInfo fileInfo(dbPath); if (!fileInfo.exists()) { QDir storageDir(fileInfo.dir()); if (!storageDir.mkpath(storageDir.path())) { BLAME() << "Could not create storage directory:" << storageDir.path(); m_error = CredentialsDbSetupFailed; return false; } setUserOwnership(storageDir.path()); } return true; } bool CredentialsAccessManager::openMetaDataDB() { QString dbPath = m_CAMConfiguration.metadataDBPath(); m_pCredentialsDB = new CredentialsDB(dbPath, m_secretsStorage); if (!m_pCredentialsDB->init()) { m_error = CredentialsDbConnectionError; return false; } return true; } void CredentialsAccessManager::closeMetaDataDB() { if (m_pCredentialsDB) { delete m_pCredentialsDB; m_pCredentialsDB = NULL; } } bool CredentialsAccessManager::openCredentialsSystem() { RETURN_IF_NOT_INITIALIZED(false); if (!openMetaDataDB()) { BLAME() << "Couldn't open metadata DB!"; return false; } m_systemOpened = true; if (m_cryptoManager->fileSystemIsMounted()) { if (!openSecretsDB()) { BLAME() << "Failed to open secrets DB."; /* Even if the secrets DB couldn't be opened, signond is still * usable: that's why we return "true" anyways. */ } } else { /* The secrets DB will be opened as soon as the encrypted FS is * mounted. */ m_cryptoManager->mountFileSystem(); } return true; } bool CredentialsAccessManager::closeCredentialsSystem() { RETURN_IF_NOT_INITIALIZED(false); if (!credentialsSystemOpened()) return true; bool allClosed = true; if (isSecretsDBOpen() && !closeSecretsDB()) allClosed = false; closeMetaDataDB(); m_error = NoError; m_systemOpened = false; return allClosed; } bool CredentialsAccessManager::deleteCredentialsSystem() { RETURN_IF_NOT_INITIALIZED(false); if (m_systemOpened && !closeCredentialsSystem()) { /* The close operation failed: we cannot proceed */ return false; } BLAME() << "Not implemented"; return false; } CredentialsDB *CredentialsAccessManager::credentialsDB() const { RETURN_IF_NOT_INITIALIZED(NULL); return m_pCredentialsDB; } bool CredentialsAccessManager::isCredentialsSystemReady() const { return (m_keyHandler != 0) ? m_keyHandler->isReady() : true; } void CredentialsAccessManager::onKeyInserted(const SignOn::Key key) { TRACE() << "Key inserted."; if (!m_keyHandler->keyIsAuthorized(key)) m_keyAuthorizer->queryKeyAuthorization( key, AbstractKeyAuthorizer::KeyInserted); } void CredentialsAccessManager::onLastAuthorizedKeyRemoved(const SignOn::Key key) { Q_UNUSED(key); TRACE() << "All keys disabled. Closing secure storage."; if (isSecretsDBOpen() || m_cryptoManager->fileSystemIsMounted()) if (!closeSecretsDB()) BLAME() << "Error occurred while closing secure storage."; } void CredentialsAccessManager::onKeyRemoved(const SignOn::Key key) { TRACE() << "Key removed."; if (m_keyHandler->keyIsAuthorized(key)) { if (!m_keyHandler->revokeKeyAuthorization(key)) { BLAME() << "Revoking key authorization failed"; } } } void CredentialsAccessManager::onKeyAuthorizationQueried(const SignOn::Key key, int result) { TRACE() << "result:" << result; if (result != AbstractKeyAuthorizer::Denied) { KeyHandler::AuthorizeFlags flags = KeyHandler::None; if (result == AbstractKeyAuthorizer::Exclusive) { TRACE() << "Reformatting secure storage."; flags |= KeyHandler::FormatStorage; } if (!m_keyHandler->authorizeKey(key, flags)) { BLAME() << "Authorization failed"; } } replyToSecureStorageEventNotifiers(); } bool CredentialsAccessManager::keysAvailable() const { if (m_keyHandler == 0) return false; return !m_keyHandler->insertedKeys().isEmpty(); } void CredentialsAccessManager::replyToSecureStorageEventNotifiers() { TRACE(); //Notify secure storage notifiers if any. int eventType = SIGNON_SECURE_STORAGE_NOT_AVAILABLE; if ((m_pCredentialsDB != 0) && m_pCredentialsDB->isSecretsDBOpen()) eventType = SIGNON_SECURE_STORAGE_AVAILABLE; // Signal objects that posted secure storage not available events foreach (EventSender object, m_secureStorageEventNotifiers) { if (object.isNull()) continue; SecureStorageEvent *secureStorageEvent = new SecureStorageEvent((QEvent::Type)eventType); QCoreApplication::postEvent( object.data(), secureStorageEvent, Qt::HighEventPriority); } m_secureStorageEventNotifiers.clear(); } void CredentialsAccessManager::customEvent(QEvent *event) { TRACE() << "Custom event received."; if (event->type() != SIGNON_SECURE_STORAGE_NOT_AVAILABLE) { QObject::customEvent(event); return; } SecureStorageEvent *localEvent = static_cast(event); /* All senders of this event will receive a reply when * the secure storage becomes available or an error occurs. */ m_secureStorageEventNotifiers.append(localEvent->m_sender); TRACE() << "Processing secure storage not available event."; if ((localEvent == 0) || (m_pCredentialsDB == 0)) { replyToSecureStorageEventNotifiers(); QObject::customEvent(event); return; } //Double check if the secrets DB is indeed unavailable if (m_pCredentialsDB->isSecretsDBOpen()) { replyToSecureStorageEventNotifiers(); QObject::customEvent(event); return; } SignOn::Key key; /* we don't specity any key */ m_keyAuthorizer->queryKeyAuthorization(key, AbstractKeyAuthorizer::StorageNeeded); QObject::customEvent(event); } void CredentialsAccessManager::onEncryptedFSMounted() { TRACE(); if (!credentialsSystemOpened()) return; if (!isSecretsDBOpen()) { if (openSecretsDB()) { TRACE() << "Secrets DB opened."; } else { BLAME() << "Failed to open secrets DB."; } } else { BLAME() << "Secrets DB already opened?"; } } void CredentialsAccessManager::onEncryptedFSUnmounting() { TRACE(); if (!credentialsSystemOpened()) return; if (isSecretsDBOpen()) { m_pCredentialsDB->closeSecretsDB(); } } signond-nicolasfella/src/signond/credentialsaccessmanager.h0000664000175000017500000003231414615454535024475 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! @file credentialsaccessmanager.h Definition of the CredentialsAccessManager object. @ingroup Accounts_and_SSO_Framework */ #ifndef CREDENTIALS_ACCESS_MANAGER_H #define CREDENTIALS_ACCESS_MANAGER_H #include "accesscontrolmanagerhelper.h" #include "credentialsdb.h" #include "signonui_interface.h" #include #include #include #include #include #include "SignOn/AbstractAccessControlManager" #include "SignOn/AbstractCryptoManager" #include "SignOn/AbstractKeyAuthorizer" #include "SignOn/AbstractKeyManager" #include "SignOn/AbstractSecretsStorage" #include "SignOn/KeyHandler" /*! * @def SIGNON_SECURE_STORAGE_NOT_AVAILABLE * Use this event type to signal the CAM when the secure storage is not * available. CAM can also reply with a event of this type if it doesn't manage * to resolve the secure storage access. * @sa SecureStorageEvent */ #define SIGNON_SECURE_STORAGE_NOT_AVAILABLE (QEvent::User + 1001) /*! * @def SIGNON_SECURE_STORAGE_AVAILABLE * The CAM will reply with an event of this type when the secure storage access * will be successfully resolved. * @sa SecureStorageEvent */ #define SIGNON_SECURE_STORAGE_AVAILABLE (QEvent::User + 1002) /** * Manager access to the Credentials DB - synchronized singleton available * everywhere in the Authentication Core module. */ namespace SignonDaemonNS { /*! * @typedef EventSender Guarded pointer for event sending objects. */ typedef QPointer EventSender; /*! * @class SecureStorageEvent * Any object in the signon framework that needs the CredentialsAccessManager - * CAM - secure storage in order to function properly can signal this event to * the CAM. * The object posting this event should reimplement the * QObject::customEvent(QEvent *event) method and handle response events of the * same type coming from the CAM upon success/failure in resolving access to * the secure storage. * @sa SIGNON_SECURE_STORAGE_NOT_AVAILABLE * @sa SIGNON_SECURE_STORAGE_AVAILABLE */ class SecureStorageEvent: public QEvent { public: SecureStorageEvent(QEvent::Type type): QEvent(type), m_sender(0) {} EventSender m_sender; /*! << The sender object of the event. */ }; /*! * @class CAMConfiguration * Configuration object for the CredentialsAccessManager - CAM. * @ingroup Accounts_and_SSO_Framework */ struct CAMConfiguration { /*! * Constructs a CAMConfiguration object with the default configuration - * encryption in use. */ CAMConfiguration(); /*! * Serializes the CAMConfiguration object as string to a specific IODevice. * @param device, must not be null. */ void serialize(QIODevice *device); /*! * Returns the path to the metadata DB. */ QString metadataDBPath() const; /*! * Returns the name of the CryptoManager to use. */ QString cryptoManagerName() const; /*! * Returns the name of the AccessControlManager to use. */ QString accessControlManagerName() const; bool useEncryption() const; /*! * Returns the name of the SecretsStorage to use. */ QString secretsStorageName() const; void setStoragePath(const QString &storagePath); void addSetting(const QString &key, const QVariant &value) { m_settings.insert(key, value); } QString m_storagePath; /*!< The base directory for storage. */ QString m_dbName; /*!< The database file name. */ QString m_secretsDbName; /*!< The credentials database file name. */ QByteArray m_encryptionPassphrase; /*!< Passphrase used for opening encrypted FS. */ QVariantMap m_settings; }; /*! * @enum, error reported by the CAM via the lastError() method. */ enum CredentialsAccessError { NoError = 0, NotInitialized, AlreadyInitialized, AccessCodeHandlerInitFailed, AccessCodeNotReady, FailedToFetchAccessCode, AccessCodeInvalid, EncryptionInUse, CredentialsDbSetupFailed, CredentialsDbMountFailed, CredentialsDbUnmountFailed, CredentialsDbDeletionFailed, CredentialsDbAlreadyDeployed, CredentialsDbAlreadyMounted, CredentialsDbNotMounted, CredentialsDbConnectionError, CredentialsDbSqlError, UnknownError }; /*! * @class CredentialsAccessManager * Main singleton and manager object of the credentials database system. * Offers access to the CredentialsDB and AccessControl objects, using a * specific configuration (e.g. Access to a SQL database created on an * encrypted file system which is mounted by this system). * Most calls of this object's methods return false or NULL in case of failure; * the specific error code can be retrieved by calling the lastError() method. * @ingroup Accounts_and_SSO_Framework * @sa CredentialsDB * @sa AccessControl * @sa AccessCodeHandler * @sa AbstractCryptoManager */ class CredentialsAccessManager: public QObject { Q_OBJECT /*! * @enum KeySwapAuthorizingMech * Core key authorization is performed through key swapping mechanisms. * This feature becomes available when the number of inserted authorized * keys reaches `0`. * - If the mechanism is `Disabled`, signon core will attemp authorizing * keys only through available AbstractKeyManager implementations that * support key authorization. * - If the mechanism is `AuthorizedKeyRemovedFirst`, signon core will * attempt authorization of a newly inserted key using its internal * already authorized keys collection. * - If the mechanism is `UnauthorizedKeyRemovedFirst`, signon core will * attempt authorization of a previously disabled unauthorized key, if * the last physically inserted key is already authorized. In this case * the disabled unauthorized key was cached when disabled, prior to its * authorization. */ enum KeySwapAuthorizingMech { Disabled = 0, /**< Signon core does not authorize keys. */ AuthorizedKeyRemovedFirst, /**< The key swap order is as suggested. */ UnauthorizedKeyRemovedFirst /**< The key swap order is as suggested. */ }; /*! * @enum StorageUiCleanupFlag * Specific options for cleaning up resources upon secure storage UI closure. * @sa KeySwapAuthorizingMech */ enum StorageUiCleanupFlag { NoFlags = 0, /**< No flags. */ DisableCoreKeyAuthorization /**< Disable any core key authorization mechanism and clears any unauthorized cached key that is not physically inserted into the device. */ }; Q_DECLARE_FLAGS(StorageUiCleanupFlags, StorageUiCleanupFlag) public: /*! * Constructs a CredentialsAccessManager object with the given parent. * @param configuration The configuration to use. * @param parent A parent QObject. */ CredentialsAccessManager(const CAMConfiguration &configuration, QObject *parent = 0); /*! * Destroys a CredentialsAccessManager. * Closes the credentials access system * - closes the database connection * - unmounts the dedicated encrypted filesystem, if in use. */ ~CredentialsAccessManager(); /*! * Returns CAM instance. */ static CredentialsAccessManager *instance(); /*! * Initializes the CAM instance. * If encryption is in use, this will start the key managers and create the * CryptoManager object, preparing everything for the mounting of the * encrypted file system. */ bool init(); /*! * Finalizes the CAM instance, this could include, closing the credentials * system and resetting the configuration. After this call the CAM needs to * be reinitialized. */ void finalize(); /*! * Adds a key manager. This method must be called before init(). * @param keyManager The key manager to add. */ void addKeyManager(SignOn::AbstractKeyManager *keyManager); /*! * Initializes know objects from an extension plugin. * @param extension A signon extension plugin. * * @returns True if the extension provides objects that the CAM is using. */ bool initExtension(QObject *object); QStringList backupFiles() const; /*! * Opens the credentials system, creates the CreadentialsDB object; if * encryption is configured this will also mount the encrypted file system, * based on the AccessControlHandler obtained keys. * First call of this method on a specific platform also does the * formatting prior to the effective opening. * * @returns true on success, false otherwise. Call lastError() to get * the error code. */ bool openCredentialsSystem(); /*! * Closes the credentials system * - closes the database connection * - if encryption is in use, unmounts the encrypted file system * This is also called by the destructor. * * @returns true on success, false otherwise. Call lastError() to get the * error code. */ bool closeCredentialsSystem(); /*! * Deletes the credentials system. * - deletes the credentials database * - if encryption is in use the encrypted file system will be deleted * @warning use this carefully. Upon successful completion this call * deletes all the stored credentials. * * @returns true on success, false otherwise. Call lastError() to get the * error code. */ bool deleteCredentialsSystem(); /*! * For convenience method. * @returns true if the credentials system is opened, false otherwise. */ bool credentialsSystemOpened() const { return m_systemOpened; } /*! * The creadentials system is ready when all of the subscribed key managers * have successfully reported all of the inserted keys. The credentials * system can be ready while at the same time the secure storage is not * opened. * * @returns true if the credentials system is ready, false otherwise. */ bool isCredentialsSystemReady() const; /*! * @returns the credentials database object. */ CredentialsDB *credentialsDB() const; /*! * @returns the CAM in use configuration. */ const CAMConfiguration &configuration() const { return m_CAMConfiguration; } /*! * @sa CredentialsAccessError * @returns the last CAM's internally reported error. */ CredentialsAccessError lastError() const { return m_error; } /*! * The CAM manages the encryption keys collection. * @returns whether the CAM detected any encryption keys or not. */ bool keysAvailable() const; Q_SIGNALS: /*! * Is emitted when the credentials system becomes ready. */ void credentialsSystemReady(); private Q_SLOTS: void onKeyInserted(const SignOn::Key key); void onLastAuthorizedKeyRemoved(const SignOn::Key key); void onKeyRemoved(const SignOn::Key key); void onKeyAuthorizationQueried(const SignOn::Key, int); void onEncryptedFSMounted(); void onEncryptedFSUnmounting(); protected: void customEvent(QEvent *event); private: bool createStorageDir(); bool openSecretsDB(); bool isSecretsDBOpen(); bool closeSecretsDB(); bool openMetaDataDB(); void closeMetaDataDB(); void replyToSecureStorageEventNotifiers(); private: static CredentialsAccessManager *m_pInstance; bool m_isInitialized; bool m_systemOpened; /* Flag indicating whether the system is ready or not. * Currently the system is ready when all of the key managers have * successfully reported all of the inserted keys. */ mutable CredentialsAccessError m_error; QList keyManagers; CredentialsDB *m_pCredentialsDB; SignOn::AbstractCryptoManager *m_cryptoManager; SignOn::KeyHandler *m_keyHandler; SignOn::AbstractKeyAuthorizer *m_keyAuthorizer; SignOn::AbstractSecretsStorage *m_secretsStorage; CAMConfiguration m_CAMConfiguration; SignOn::AbstractAccessControlManager *m_acManager; AccessControlManagerHelper *m_acManagerHelper; /* List of all the senders of a SecureStorageEvent. */ QList m_secureStorageEventNotifiers; }; } //namespace SignonDaemonNS #endif // CREDENTIALS_ACCESS_MANAGER_H signond-nicolasfella/src/signond/credentialsdb.cpp0000664000175000017500000014650414615454535022630 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "credentialsdb.h" #include "credentialsdb_p.h" #include "signond-common.h" #include "signonidentityinfo.h" #include "signonsessioncoretools.h" #define INIT_ERROR() ErrorMonitor errorMonitor(this) #define RETURN_IF_NO_SECRETS_DB(retval) \ if (!isSecretsDBOpen()) { \ TRACE() << "Secrets DB is not available"; \ _lastError = noSecretsDB; return retval; \ } #define S(s) QLatin1String(s) namespace SignonDaemonNS { static const QString driver = QLatin1String("QSQLITE"); bool SecretsCache::lookupCredentials(quint32 id, QString &username, QString &password) const { QHash::const_iterator i; i = m_cache.find(id); if (i == m_cache.end()) return false; username = i->m_username; password = i->m_password; return true; } QVariantMap SecretsCache::lookupData(quint32 id, quint32 method) const { return m_cache.value(id).m_blobData.value(method); } void SecretsCache::updateCredentials(quint32 id, const QString &username, const QString &password, bool storePassword) { if (id == 0) return; AuthCache &credentials = m_cache[id]; credentials.m_username = username; credentials.m_password = password; credentials.m_storePassword = storePassword; } void SecretsCache::updateData(quint32 id, quint32 method, const QVariantMap &data) { if (id == 0) return; AuthCache &credentials = m_cache[id]; credentials.m_blobData[method] = data; } void SecretsCache::storeToDB(SignOn::AbstractSecretsStorage *secretsStorage) const { if (m_cache.isEmpty()) return; TRACE() << "Storing cached credentials into permanent storage"; QHash::const_iterator i; for (i = m_cache.constBegin(); i != m_cache.constEnd(); i++) { quint32 id = i.key(); const AuthCache &cache = i.value(); /* Store the credentials */ QString password = cache.m_storePassword ? cache.m_password : QString(); if (!cache.m_username.isEmpty() || !password.isEmpty()) { secretsStorage->updateCredentials(id, cache.m_username, password); } /* Store any binary blobs */ QHash::const_iterator j; for (j = cache.m_blobData.constBegin(); j != cache.m_blobData.constEnd(); j++) { quint32 method = j.key(); secretsStorage->storeData(id, method, j.value()); } } } void SecretsCache::clear() { m_cache.clear(); } SqlDatabase::SqlDatabase(const QString &databaseName, const QString &connectionName, int version): m_lastError(SignOn::CredentialsDBError()), m_version(version), m_database(QSqlDatabase::addDatabase(driver, connectionName)) { TRACE() << "Supported Drivers:" << this->supportedDrivers(); TRACE() << "DATABASE NAME [" << databaseName << "]"; m_database.setDatabaseName(databaseName); } SqlDatabase::~SqlDatabase() { m_database.commit(); m_database.close(); } bool SqlDatabase::init() { if (!connect()) return false; TRACE() << "Database connection succeeded."; if (!hasTables()) { TRACE() << "Creating SQL table structure..."; if (!createTables()) return false; if (!SqlDatabase::updateDB(m_version)) BLAME() << "Failed to set database version to: " << m_version << ".This could lead to data loss."; } else { TRACE() << "SQL table structure already created..."; // check the DB version QSqlQuery q = exec(S("PRAGMA user_version")); int oldVersion = q.first() ? q.value(0).toInt() : 0; if (oldVersion < m_version) updateDB(oldVersion); } return true; } bool SqlDatabase::updateDB(int version) { TRACE() << "Update DB from version " << version << " to " << m_version; exec(QString::fromLatin1("PRAGMA user_version = %1").arg(m_version)); return true; } bool SqlDatabase::connect() { if (!m_database.open()) { TRACE() << "Could not open database connection.\n"; setLastError(m_database.lastError()); return false; } return true; } void SqlDatabase::disconnect() { m_database.close(); } bool SqlDatabase::startTransaction() { return m_database.transaction(); } bool SqlDatabase::commit() { return m_database.commit(); } void SqlDatabase::rollback() { if (!m_database.rollback()) TRACE() << "Rollback failed, db data integrity could be compromised."; } QSqlQuery SqlDatabase::exec(const QString &queryStr) { QSqlQuery query(QString(), m_database); if (!query.prepare(queryStr)) TRACE() << "Query prepare warning: " << query.lastQuery(); if (!query.exec()) { TRACE() << "Query exec error: " << query.lastQuery(); setLastError(query.lastError()); TRACE() << errorInfo(query.lastError()); } else m_lastError.clear(); return query; } QSqlQuery SqlDatabase::exec(QSqlQuery &query) { if (!query.exec()) { TRACE() << "Query exec error: " << query.lastQuery(); setLastError(query.lastError()); TRACE() << errorInfo(query.lastError()); } else m_lastError.clear(); return query; } bool SqlDatabase::transactionalExec(const QStringList &queryList) { if (!startTransaction()) { setLastError(m_database.lastError()); TRACE() << "Could not start transaction"; return false; } bool allOk = true; foreach (QString queryStr, queryList) { TRACE() << QString::fromLatin1("TRANSACT Query [%1]").arg(queryStr); QSqlQuery query = exec(queryStr); if (errorOccurred()) { allOk = false; break; } } if (allOk && commit()) { TRACE() << "Commit SUCCEEDED."; return true; } else { rollback(); } TRACE() << "Transactional exec FAILED!"; return false; } SignOn::CredentialsDBError SqlDatabase::lastError() const { return m_lastError; } void SqlDatabase::setLastError(const QSqlError &sqlError) { if (sqlError.isValid()) { if (sqlError.type() == QSqlError::ConnectionError) { m_lastError.setType(SignOn::CredentialsDBError::ConnectionError); } else { m_lastError.setType(SignOn::CredentialsDBError::StatementError); } m_lastError.setText(sqlError.text()); } else { m_lastError.clear(); } } QString SqlDatabase::errorInfo(const QSqlError &error) { if (!error.isValid()) return QLatin1String("SQL Error invalid."); QString text; QTextStream stream(&text); stream << "SQL error description:"; stream << "\n\tType: "; const char *errType; switch (error.type()) { case QSqlError::NoError: errType = "NoError"; break; case QSqlError::ConnectionError: errType = "ConnectionError"; break; case QSqlError::StatementError: errType = "StatementError"; break; case QSqlError::TransactionError: errType = "TransactionError"; break; case QSqlError::UnknownError: /* fall trough */ default: errType = "UnknownError"; } stream << errType; stream << "\n\tDatabase text: " << error.databaseText(); stream << "\n\tDriver text: " << error.driverText(); stream << "\n\tError code: " << error.nativeErrorCode(); return text; } QStringList SqlDatabase::queryList(const QString &query_str) { QSqlQuery query(QString(), m_database); if (!query.prepare(query_str)) TRACE() << "Query prepare warning: " << query.lastQuery(); return queryList(query); } QStringList SqlDatabase::queryList(QSqlQuery &q) { QStringList list; QSqlQuery query = exec(q); if (errorOccurred()) return list; while (query.next()) { list.append(query.value(0).toString()); } query.clear(); return list; } QStringList MetaDataDB::tableUpdates2() { QStringList tableUpdates = QStringList() << QString::fromLatin1( "CREATE TABLE OWNER" "(rowid INTEGER PRIMARY KEY AUTOINCREMENT," "identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES CREDENTIALS(id) ON DELETE CASCADE," "token_id INTEGER CONSTRAINT fk_token_id REFERENCES TOKENS(id) ON DELETE CASCADE)") //added triggers for OWNER << QString::fromLatin1( // Foreign Key Preventing insert "CREATE TRIGGER fki_OWNER_token_id_TOKENS_id " "BEFORE INSERT ON [OWNER] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'insert on table OWNER violates foreign key constraint fki_OWNER_token_id_TOKENS_id') " " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; " "END; " ) << QString::fromLatin1( // Foreign key preventing update "CREATE TRIGGER fku_OWNER_token_id_TOKENS_id " "BEFORE UPDATE ON [OWNER] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'update on table OWNER violates foreign key constraint fku_OWNER_token_id_TOKENS_id') " " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; " "END; " ) << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER fkdc_OWNER_token_id_TOKENS_id " "BEFORE DELETE ON TOKENS " "FOR EACH ROW BEGIN " " DELETE FROM OWNER WHERE OWNER.token_id = OLD.id; " "END; " ); return tableUpdates; } bool MetaDataDB::createTables() { /* !!! Foreign keys support seems to be disabled, for the moment... */ QStringList createTableQuery = QStringList() << QString::fromLatin1( "CREATE TABLE CREDENTIALS" "(id INTEGER PRIMARY KEY AUTOINCREMENT," "caption TEXT," "username TEXT," "flags INTEGER," "type INTEGER)") << QString::fromLatin1( "CREATE TABLE METHODS" "(id INTEGER PRIMARY KEY AUTOINCREMENT," "method TEXT UNIQUE)") << QString::fromLatin1( "CREATE TABLE MECHANISMS" "(id INTEGER PRIMARY KEY AUTOINCREMENT," "mechanism TEXT UNIQUE)") << QString::fromLatin1( "CREATE TABLE TOKENS" "(id INTEGER PRIMARY KEY AUTOINCREMENT," "token TEXT UNIQUE)") << QString::fromLatin1( "CREATE TABLE REALMS" "(identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES CREDENTIALS(id) ON DELETE CASCADE," "realm TEXT," "hostname TEXT," "PRIMARY KEY (identity_id, realm, hostname))") << QString::fromLatin1( "CREATE TABLE ACL" "(rowid INTEGER PRIMARY KEY AUTOINCREMENT," "identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES CREDENTIALS(id) ON DELETE CASCADE," "method_id INTEGER CONSTRAINT fk_method_id REFERENCES METHODS(id) ON DELETE CASCADE," "mechanism_id INTEGER CONSTRAINT fk_mechanism_id REFERENCES MECHANISMS(id) ON DELETE CASCADE," "token_id INTEGER CONSTRAINT fk_token_id REFERENCES TOKENS(id) ON DELETE CASCADE)") << QString::fromLatin1( "CREATE TABLE REFS" "(identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES CREDENTIALS(id) ON DELETE CASCADE," "token_id INTEGER CONSTRAINT fk_token_id REFERENCES TOKENS(id) ON DELETE CASCADE," "ref TEXT," "PRIMARY KEY (identity_id, token_id, ref))") /* * triggers generated with * http://www.rcs-comp.com/site/index.php/view/Utilities-SQLite_foreign_key_trigger_generator */ //insert triggers to force foreign keys support << QString::fromLatin1( // Foreign Key Preventing insert "CREATE TRIGGER fki_REALMS_identity_id_CREDENTIALS_id " "BEFORE INSERT ON [REALMS] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'insert on table REALMS violates foreign key constraint fki_REALMS_identity_id_CREDENTIALS_id') " " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; " "END; " ) << QString::fromLatin1( // Foreign key preventing update "CREATE TRIGGER fku_REALMS_identity_id_CREDENTIALS_id " "BEFORE UPDATE ON [REALMS] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'update on table REALMS violates foreign key constraint fku_REALMS_identity_id_CREDENTIALS_id') " " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; " "END; " ) << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER fkdc_REALMS_identity_id_CREDENTIALS_id " "BEFORE DELETE ON CREDENTIALS " "FOR EACH ROW BEGIN " " DELETE FROM REALMS WHERE REALMS.identity_id = OLD.id; " "END; " ) << QString::fromLatin1( // Foreign Key Preventing insert "CREATE TRIGGER fki_ACL_identity_id_CREDENTIALS_id " "BEFORE INSERT ON [ACL] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign key constraint fki_ACL_identity_id_CREDENTIALS_id') " " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; " "END;" ) << QString::fromLatin1( // Foreign key preventing update "CREATE TRIGGER fku_ACL_identity_id_CREDENTIALS_id " "BEFORE UPDATE ON [ACL] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign key constraint fku_ACL_identity_id_CREDENTIALS_id') " " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; " "END; " ) << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER fkdc_ACL_identity_id_CREDENTIALS_id " "BEFORE DELETE ON CREDENTIALS " "FOR EACH ROW BEGIN " " DELETE FROM ACL WHERE ACL.identity_id = OLD.id; " "END; " ) << QString::fromLatin1( // Foreign Key Preventing insert "CREATE TRIGGER fki_ACL_method_id_METHODS_id " "BEFORE INSERT ON [ACL] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign key constraint fki_ACL_method_id_METHODS_id') " " WHERE NEW.method_id IS NOT NULL AND (SELECT id FROM METHODS WHERE id = NEW.method_id) IS NULL; " "END; " ) << QString::fromLatin1( // Foreign key preventing update "CREATE TRIGGER fku_ACL_method_id_METHODS_id " "BEFORE UPDATE ON [ACL] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign key constraint fku_ACL_method_id_METHODS_id') " " WHERE NEW.method_id IS NOT NULL AND (SELECT id FROM METHODS WHERE id = NEW.method_id) IS NULL; " "END; " ) << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER fkdc_ACL_method_id_METHODS_id " "BEFORE DELETE ON METHODS " "FOR EACH ROW BEGIN " " DELETE FROM ACL WHERE ACL.method_id = OLD.id; " "END; " ) << QString::fromLatin1( // Foreign Key Preventing insert "CREATE TRIGGER fki_ACL_mechanism_id_MECHANISMS_id " "BEFORE INSERT ON [ACL] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign key constraint fki_ACL_mechanism_id_MECHANISMS_id') " " WHERE NEW.mechanism_id IS NOT NULL AND (SELECT id FROM MECHANISMS WHERE id = NEW.mechanism_id) IS NULL; " "END; " ) << QString::fromLatin1( // Foreign key preventing update "CREATE TRIGGER fku_ACL_mechanism_id_MECHANISMS_id " "BEFORE UPDATE ON [ACL] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign key constraint fku_ACL_mechanism_id_MECHANISMS_id') " " WHERE NEW.mechanism_id IS NOT NULL AND (SELECT id FROM MECHANISMS WHERE id = NEW.mechanism_id) IS NULL; " "END; " ) << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER fkdc_ACL_mechanism_id_MECHANISMS_id " "BEFORE DELETE ON MECHANISMS " "FOR EACH ROW BEGIN " " DELETE FROM ACL WHERE ACL.mechanism_id = OLD.id; " "END; " ) << QString::fromLatin1( // Foreign Key Preventing insert "CREATE TRIGGER fki_ACL_token_id_TOKENS_id " "BEFORE INSERT ON [ACL] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign key constraint fki_ACL_token_id_TOKENS_id') " " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; " "END; " ) << QString::fromLatin1( // Foreign key preventing update "CREATE TRIGGER fku_ACL_token_id_TOKENS_id " "BEFORE UPDATE ON [ACL] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign key constraint fku_ACL_token_id_TOKENS_id') " " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; " "END; " ) << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER fkdc_ACL_token_id_TOKENS_id " "BEFORE DELETE ON TOKENS " "FOR EACH ROW BEGIN " " DELETE FROM ACL WHERE ACL.token_id = OLD.id; " "END; " ) << QString::fromLatin1( // Foreign Key Preventing insert "CREATE TRIGGER fki_REFS_identity_id_CREDENTIALS_id " "BEFORE INSERT ON [REFS] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'insert on table REFS violates foreign key constraint fki_REFS_identity_id_CREDENTIALS_id') " " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; " "END; " ) << QString::fromLatin1( // Foreign key preventing update "CREATE TRIGGER fku_REFS_identity_id_CREDENTIALS_id " "BEFORE UPDATE ON [REFS] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'update on table REFS violates foreign key constraint fku_REFS_identity_id_CREDENTIALS_id') " " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; " "END; " ) << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER fkdc_REFS_identity_id_CREDENTIALS_id " "BEFORE DELETE ON CREDENTIALS " "FOR EACH ROW BEGIN " " DELETE FROM REFS WHERE REFS.identity_id = OLD.id; " "END; " ) << QString::fromLatin1( // Foreign Key Preventing insert "CREATE TRIGGER fki_REFS_token_id_TOKENS_id " "BEFORE INSERT ON [REFS] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'insert on table REFS violates foreign key constraint fki_REFS_token_id_TOKENS_id') " " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; " "END; " ) << QString::fromLatin1( // Foreign key preventing update "CREATE TRIGGER fku_REFS_token_id_TOKENS_id " "BEFORE UPDATE ON [REFS] " "FOR EACH ROW BEGIN " " SELECT RAISE(ROLLBACK, 'update on table REFS violates foreign key constraint fku_REFS_token_id_TOKENS_id') " " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; " "END; " ) << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER fkdc_REFS_token_id_TOKENS_id " "BEFORE DELETE ON TOKENS " "FOR EACH ROW BEGIN " " DELETE FROM REFS WHERE REFS.token_id = OLD.id; " "END; " ); /* end of generated code */ //insert table updates createTableQuery << tableUpdates2(); foreach (QString createTable, createTableQuery) { QSqlQuery query = exec(createTable); if (lastError().isValid()) { TRACE() << "Error occurred while creating the database."; return false; } query.clear(); commit(); } TRACE() << "Creation successful"; return true; } bool MetaDataDB::updateDB(int version) { if (version == m_version) return true; if (version < 1) { TRACE() << "Upgrading from version < 1 not supported. Clearing DB"; QString fileName = m_database.databaseName(); QString connectionName = m_database.connectionName(); m_database.close(); QFile::remove(fileName); m_database = QSqlDatabase(QSqlDatabase::addDatabase(driver, connectionName)); m_database.setDatabaseName(fileName); if (!connect()) return false; if (!createTables()) return false; } //convert from 1 to 2 if (version == 1) { QStringList createTableQuery = tableUpdates2(); foreach (QString createTable, createTableQuery) { QSqlQuery query = exec(createTable); if (lastError().isValid()) { TRACE() << "Error occurred while inseting new tables."; return false; } query.clear(); commit(); } TRACE() << "Table insert successful"; //populate owner table from acl QSqlQuery ownerInsert = exec(S("INSERT OR IGNORE INTO OWNER " "(identity_id, token_id) " " SELECT identity_id, token_id FROM ACL")); if (!commit()){ BLAME() << "Table copy failed."; rollback(); } } else { return false; } return SqlDatabase::updateDB(version); } QStringList MetaDataDB::methods(const quint32 id, const QString &securityToken) { QStringList list; if (securityToken.isEmpty()) { list = queryList( QString::fromLatin1("SELECT DISTINCT METHODS.method FROM " "( ACL JOIN METHODS ON ACL.method_id = METHODS.id ) " "WHERE ACL.identity_id = '%1'").arg(id) ); return list; } QSqlQuery q = newQuery(); q.prepare(S("SELECT DISTINCT METHODS.method FROM " "( ACL JOIN METHODS ON ACL.method_id = METHODS.id) " "WHERE ACL.identity_id = :id AND ACL.token_id = " "(SELECT id FROM TOKENS where token = :token)")); q.bindValue(S(":id"), id); q.bindValue(S(":token"), securityToken); list = queryList(q); return list; } quint32 MetaDataDB::methodId(const QString &method) { TRACE() << "method:" << method; QSqlQuery q = newQuery(); q.prepare(S("SELECT id FROM METHODS WHERE method = :method")); q.bindValue(S(":method"), method); exec(q); if (!q.first()) { TRACE() << "No result or invalid method query."; return 0; } return q.value(0).toUInt(); } SignonIdentityInfo MetaDataDB::identity(const quint32 id) { QString query_str; query_str = QString::fromLatin1( "SELECT caption, username, flags, type " "FROM credentials WHERE id = %1").arg(id); QSqlQuery query = exec(query_str); if (!query.first()) { TRACE() << "No result or invalid credentials query."; return SignonIdentityInfo(); } QString caption = query.value(0).toString(); QString username = query.value(1).toString(); int flags = query.value(2).toInt(); bool savePassword = flags & RememberPassword; bool validated = flags & Validated; bool isUserNameSecret = flags & UserNameIsSecret; if (isUserNameSecret) username = QString(); int type = query.value(3).toInt(); query.clear(); QStringList realms = queryList( QString::fromLatin1("SELECT realm FROM REALMS " "WHERE identity_id = %1").arg(id)); QStringList ownerTokens = queryList( QString::fromLatin1("SELECT token FROM TOKENS " "WHERE id IN " "(SELECT token_id FROM OWNER WHERE identity_id = '%1' )") .arg(id)); query_str = QString::fromLatin1("SELECT token FROM TOKENS " "WHERE id IN " "(SELECT token_id FROM ACL WHERE identity_id = '%1' )") .arg(id); query = exec(query_str); QStringList securityTokens; while (query.next()) { securityTokens.append(query.value(0).toString()); } query.clear(); MethodMap methods; query_str = QString::fromLatin1( "SELECT DISTINCT ACL.method_id, METHODS.method FROM " "( ACL JOIN METHODS ON ACL.method_id = METHODS.id ) " "WHERE ACL.identity_id = '%1'").arg(id); query = exec(query_str); while (query.next()) { QStringList mechanisms = queryList( QString::fromLatin1("SELECT DISTINCT MECHANISMS.mechanism FROM " "( MECHANISMS JOIN ACL " "ON ACL.mechanism_id = MECHANISMS.id ) " "WHERE ACL.method_id = '%1' AND ACL.identity_id = '%2' ") .arg(query.value(0).toInt()).arg(id)); methods.insert(query.value(1).toString(), mechanisms); } query.clear(); int refCount = 0; //TODO query for refcount SignonIdentityInfo info; info.setId(id); if (!isUserNameSecret) info.setUserName(username); info.setStorePassword(savePassword); info.setCaption(caption); info.setMethods(methods); info.setRealms(realms); info.setAccessControlList(securityTokens); info.setOwnerList(ownerTokens); info.setType(type); info.setRefCount(refCount); info.setValidated(validated); info.setUserNameSecret(isUserNameSecret); return info; } QList MetaDataDB::identities(const QMap &filter) { TRACE(); Q_UNUSED(filter) QList result; QString queryStr(QString::fromLatin1("SELECT id FROM credentials")); // TODO - process filtering step here !!! queryStr += QString::fromLatin1(" ORDER BY id"); QSqlQuery query = exec(queryStr); if (errorOccurred()) { TRACE() << "Error occurred while fetching credentials from database."; return result; } while (query.next()) { SignonIdentityInfo info = identity(query.value(0).toUInt()); if (errorOccurred()) break; result << info; } query.clear(); return result; } quint32 MetaDataDB::updateIdentity(const SignonIdentityInfo &info) { if (!startTransaction()) { TRACE() << "Could not start transaction. Error inserting credentials."; return 0; } quint32 id = updateCredentials(info); if (id == 0) { rollback(); return 0; } /* Methods inserts */ insertMethods(info.methods()); if (!updateRealms(id, info.realms(), info.isNew())) { TRACE() << "Error in updating realms"; rollback(); return 0; } /* Security tokens insert */ foreach (QString token, info.accessControlList()) { QSqlQuery tokenInsert = newQuery(); tokenInsert.prepare(S("INSERT OR IGNORE INTO TOKENS (token) " "VALUES ( :token )")); tokenInsert.bindValue(S(":token"), token); exec(tokenInsert); } foreach (QString token, info.ownerList()) { if (!token.isEmpty()) { QSqlQuery tokenInsert = newQuery(); tokenInsert.prepare(S("INSERT OR IGNORE INTO TOKENS (token) " "VALUES ( :token )")); tokenInsert.bindValue(S(":token"), token); exec(tokenInsert); } } if (!info.isNew()) { //remove acl QString queryStr = QString::fromLatin1( "DELETE FROM ACL WHERE " "identity_id = '%1'") .arg(info.id()); QSqlQuery insertQuery = exec(queryStr); insertQuery.clear(); //remove owner queryStr = QString::fromLatin1( "DELETE FROM OWNER WHERE " "identity_id = '%1'") .arg(info.id()); insertQuery = exec(queryStr); insertQuery.clear(); } /* ACL insert, this will do basically identity level ACL */ QMapIterator it(info.methods()); while (it.hasNext()) { it.next(); if (!info.accessControlList().isEmpty()) { foreach (QString token, info.accessControlList()) { foreach (QString mech, it.value()) { QSqlQuery aclInsert = newQuery(); aclInsert.prepare(S("INSERT OR REPLACE INTO ACL " "(identity_id, method_id, mechanism_id, token_id) " "VALUES ( :id, " "( SELECT id FROM METHODS WHERE method = :method )," "( SELECT id FROM MECHANISMS WHERE mechanism= :mech ), " "( SELECT id FROM TOKENS WHERE token = :token ))")); aclInsert.bindValue(S(":id"), id); aclInsert.bindValue(S(":method"), it.key()); aclInsert.bindValue(S(":mech"), mech); aclInsert.bindValue(S(":token"), token); exec(aclInsert); } //insert entires for empty mechs list if (it.value().isEmpty()) { QSqlQuery aclInsert = newQuery(); aclInsert.prepare(S("INSERT OR REPLACE INTO ACL (identity_id, method_id, token_id) " "VALUES ( :id, " "( SELECT id FROM METHODS WHERE method = :method )," "( SELECT id FROM TOKENS WHERE token = :token ))")); aclInsert.bindValue(S(":id"), id); aclInsert.bindValue(S(":method"), it.key()); aclInsert.bindValue(S(":token"), token); exec(aclInsert); } } } else { foreach (QString mech, it.value()) { QSqlQuery aclInsert = newQuery(); aclInsert.prepare(S("INSERT OR REPLACE INTO ACL " "(identity_id, method_id, mechanism_id) " "VALUES ( :id, " "( SELECT id FROM METHODS WHERE method = :method )," "( SELECT id FROM MECHANISMS WHERE mechanism= :mech )" ")")); aclInsert.bindValue(S(":id"), id); aclInsert.bindValue(S(":method"), it.key()); aclInsert.bindValue(S(":mech"), mech); exec(aclInsert); } //insert entires for empty mechs list if (it.value().isEmpty()) { QSqlQuery aclInsert = newQuery(); aclInsert.prepare(S("INSERT OR REPLACE INTO ACL (identity_id, method_id) " "VALUES ( :id, " "( SELECT id FROM METHODS WHERE method = :method )" ")")); aclInsert.bindValue(S(":id"), id); aclInsert.bindValue(S(":method"), it.key()); exec(aclInsert); } } } //insert acl in case where methods are missing if (info.methods().isEmpty()) { foreach (QString token, info.accessControlList()) { QSqlQuery aclInsert = newQuery(); aclInsert.prepare(S("INSERT OR REPLACE INTO ACL " "(identity_id, token_id) " "VALUES ( :id, " "( SELECT id FROM TOKENS WHERE token = :token ))")); aclInsert.bindValue(S(":id"), id); aclInsert.bindValue(S(":token"), token); exec(aclInsert); } } //insert owner list foreach (QString token, info.ownerList()) { if (!token.isEmpty()) { QSqlQuery ownerInsert = newQuery(); ownerInsert.prepare(S("INSERT OR REPLACE INTO OWNER " "(identity_id, token_id) " "VALUES ( :id, " "( SELECT id FROM TOKENS WHERE token = :token ))")); ownerInsert.bindValue(S(":id"), id); ownerInsert.bindValue(S(":token"), token); exec(ownerInsert); } } if (commit()) { return id; } else { rollback(); TRACE() << "Credentials insertion failed."; return 0; } } bool MetaDataDB::removeIdentity(const quint32 id) { TRACE(); QStringList queries = QStringList() << QString::fromLatin1( "DELETE FROM CREDENTIALS WHERE id = %1").arg(id) << QString::fromLatin1( "DELETE FROM ACL WHERE identity_id = %1").arg(id) << QString::fromLatin1( "DELETE FROM REALMS WHERE identity_id = %1").arg(id) << QString::fromLatin1( "DELETE FROM owner WHERE identity_id = %1").arg(id); return transactionalExec(queries); } bool MetaDataDB::clear() { TRACE(); QStringList clearCommands = QStringList() << QLatin1String("DELETE FROM CREDENTIALS") << QLatin1String("DELETE FROM METHODS") << QLatin1String("DELETE FROM MECHANISMS") << QLatin1String("DELETE FROM ACL") << QLatin1String("DELETE FROM REALMS") << QLatin1String("DELETE FROM TOKENS") << QLatin1String("DELETE FROM OWNER"); return transactionalExec(clearCommands); } QStringList MetaDataDB::accessControlList(const quint32 identityId) { return queryList(QString::fromLatin1("SELECT token FROM TOKENS " "WHERE id IN " "(SELECT token_id FROM ACL WHERE identity_id = '%1' )") .arg(identityId)); } QStringList MetaDataDB::ownerList(const quint32 identityId) { return queryList(QString::fromLatin1("SELECT token FROM TOKENS " "WHERE id IN " "(SELECT token_id FROM OWNER WHERE identity_id = '%1' )") .arg(identityId)); } bool MetaDataDB::addReference(const quint32 id, const QString &token, const QString &reference) { if (!startTransaction()) { TRACE() << "Could not start transaction. Error inserting data."; return false; } TRACE() << "Storing:" << id << ", " << token << ", " << reference; /* Data insert */ bool allOk = true; /* Security token insert */ QSqlQuery tokenInsert = newQuery(); tokenInsert.prepare(S("INSERT OR IGNORE INTO TOKENS (token) " "VALUES ( :token )")); tokenInsert.bindValue(S(":token"), token); exec(tokenInsert); if (errorOccurred()) { allOk = false; } QSqlQuery refsInsert = newQuery(); refsInsert.prepare(S("INSERT OR REPLACE INTO REFS " "(identity_id, token_id, ref) " "VALUES ( :id, " "( SELECT id FROM TOKENS WHERE token = :token )," ":reference" ")")); refsInsert.bindValue(S(":id"), id); refsInsert.bindValue(S(":token"), token); refsInsert.bindValue(S(":reference"), reference); exec(refsInsert); if (errorOccurred()) { allOk = false; } if (allOk && commit()) { TRACE() << "Data insertion ok."; return true; } rollback(); TRACE() << "Data insertion failed."; return false; } bool MetaDataDB::removeReference(const quint32 id, const QString &token, const QString &reference) { TRACE() << "Removing:" << id << ", " << token << ", " << reference; //check that there is references QStringList refs = references(id, token); if (refs.isEmpty()) return false; if (!reference.isNull() && !refs.contains(reference)) return false; if (!startTransaction()) { TRACE() << "Could not start transaction. Error removing data."; return false; } bool allOk = true; QSqlQuery refsDelete = newQuery(); if (reference.isEmpty()) { refsDelete.prepare(S("DELETE FROM REFS " "WHERE identity_id = :id AND " "token_id = ( SELECT id FROM TOKENS WHERE token = :token )")); refsDelete.bindValue(S(":id"), id); refsDelete.bindValue(S(":token"), token); } else { refsDelete.prepare(S("DELETE FROM REFS " "WHERE identity_id = :id AND " "token_id = ( SELECT id FROM TOKENS WHERE token = :token ) " "AND ref = :ref")); refsDelete.bindValue(S(":id"), id); refsDelete.bindValue(S(":token"), token); refsDelete.bindValue(S(":ref"), reference); } exec(refsDelete); if (errorOccurred()) { allOk = false; } if (allOk && commit()) { TRACE() << "Data delete ok."; return true; } rollback(); TRACE() << "Data delete failed."; return false; } QStringList MetaDataDB::references(const quint32 id, const QString &token) { if (token.isEmpty()) return queryList(QString::fromLatin1("SELECT ref FROM REFS " "WHERE identity_id = '%1'") .arg(id)); QSqlQuery q = newQuery(); q.prepare(S("SELECT ref FROM REFS " "WHERE identity_id = :id AND " "token_id = (SELECT id FROM TOKENS WHERE token = :token )")); q.bindValue(S(":id"), id); q.bindValue(S(":token"), token); return queryList(q); } bool MetaDataDB::insertMethods(QMap methods) { bool allOk = true; if (methods.isEmpty()) return false; //insert (unique) method names QMapIterator it(methods); while (it.hasNext()) { it.next(); QSqlQuery methodInsert = newQuery(); methodInsert.prepare(S("INSERT OR IGNORE INTO METHODS (method) " "VALUES( :method )")); methodInsert.bindValue(S(":method"), it.key()); exec(methodInsert); if (errorOccurred()) allOk = false; //insert (unique) mechanism names foreach (QString mech, it.value()) { QSqlQuery mechInsert = newQuery(); mechInsert.prepare(S("INSERT OR IGNORE INTO MECHANISMS (mechanism) " "VALUES( :mech )")); mechInsert.bindValue(S(":mech"), mech); exec(mechInsert); if (errorOccurred()) allOk = false; } } return allOk; } quint32 MetaDataDB::insertMethod(const QString &method, bool *ok) { QSqlQuery q = newQuery(); q.prepare(S("INSERT INTO METHODS (method) VALUES(:method)")); q.bindValue(S(":method"), method); exec(q); if (errorOccurred()) { if (ok != 0) *ok = false; return 0; } return q.lastInsertId().toUInt(ok); } quint32 MetaDataDB::updateCredentials(const SignonIdentityInfo &info) { quint32 id; QSqlQuery q = newQuery(); int flags = 0; if (info.validated()) flags |= Validated; if (info.storePassword()) flags |= RememberPassword; if (info.isUserNameSecret()) flags |= UserNameIsSecret; if (!info.isNew()) { TRACE() << "UPDATE:" << info.id() ; q.prepare(S("UPDATE CREDENTIALS SET caption = :caption, " "username = :username, " "flags = :flags, " "type = :type WHERE id = :id")); q.bindValue(S(":id"), info.id()); } else { TRACE() << "INSERT:" << info.id(); q.prepare(S("INSERT INTO CREDENTIALS " "(caption, username, flags, type) " "VALUES(:caption, :username, :flags, :type)")); } q.bindValue(S(":username"), info.isUserNameSecret() ? QString() : info.userName()); q.bindValue(S(":caption"), info.caption()); q.bindValue(S(":flags"), flags); q.bindValue(S(":type"), info.type()); exec(q); if (errorOccurred()) { TRACE() << "Error occurred while updating crendentials"; return 0; } if (info.isNew()) { /* Fetch id of the inserted credentials */ QVariant idVariant = q.lastInsertId(); if (!idVariant.isValid()) { TRACE() << "Error occurred while inserting crendentials"; return 0; } id = idVariant.toUInt(); } else { id = info.id() ; } return id; } bool MetaDataDB::updateRealms(quint32 id, const QStringList &realms, bool isNew) { QString queryStr; if (!isNew) { //remove realms list queryStr = QString::fromLatin1( "DELETE FROM REALMS WHERE identity_id = '%1'") .arg(id); exec(queryStr); } /* Realms insert */ QSqlQuery q = newQuery(); q.prepare(S("INSERT OR IGNORE INTO REALMS (identity_id, realm) " "VALUES (:id, :realm)")); foreach (QString realm, realms) { q.bindValue(S(":id"), id); q.bindValue(S(":realm"), realm); exec(q); if (errorOccurred()) return false; } return true; } /* Error monitor class */ CredentialsDB::ErrorMonitor::ErrorMonitor(CredentialsDB *db) { db->_lastError.setType(SignOn::CredentialsDBError::NoError); db->metaDataDB->clearError(); if (db->secretsStorage != 0) db->secretsStorage->clearError(); _db = db; } CredentialsDB::ErrorMonitor::~ErrorMonitor() { /* If there's an error set on the CredentialsDB, just let it be and return. * If not, take the error from the SqlDatabase objects, if any. */ if (_db->_lastError.isValid()) return; if (_db->secretsStorage != 0 && _db->secretsStorage->lastError().isValid()) { _db->_lastError = _db->secretsStorage->lastError(); return; } _db->_lastError = _db->metaDataDB->lastError(); } /* ------- CredentialsDB implementation ------- */ CredentialsDB::CredentialsDB(const QString &metaDataDbName, SignOn::AbstractSecretsStorage *secretsStorage): secretsStorage(secretsStorage), m_secretsCache(new SecretsCache), metaDataDB(new MetaDataDB(metaDataDbName)) { noSecretsDB = SignOn::CredentialsDBError( QLatin1String("Secrets DB not opened"), SignOn::CredentialsDBError::ConnectionError); } CredentialsDB::~CredentialsDB() { TRACE(); delete m_secretsCache; if (metaDataDB) { QString connectionName = metaDataDB->connectionName(); delete metaDataDB; QSqlDatabase::removeDatabase(connectionName); } } bool CredentialsDB::init() { return metaDataDB->init(); } bool CredentialsDB::openSecretsDB(const QString &secretsDbName) { QVariantMap configuration; configuration.insert(QLatin1String("name"), secretsDbName); if (!secretsStorage->initialize(configuration)) { TRACE() << "SecretsStorage initialization failed: " << secretsStorage->lastError().text(); return false; } m_secretsCache->storeToDB(secretsStorage); m_secretsCache->clear(); return true; } bool CredentialsDB::isSecretsDBOpen() { return secretsStorage != 0 && secretsStorage->isOpen(); } void CredentialsDB::closeSecretsDB() { if (secretsStorage != 0) secretsStorage->close(); } SignOn::CredentialsDBError CredentialsDB::lastError() const { return _lastError; } QStringList CredentialsDB::methods(const quint32 id, const QString &securityToken) { INIT_ERROR(); return metaDataDB->methods(id, securityToken); } bool CredentialsDB::checkPassword(const quint32 id, const QString &username, const QString &password) { INIT_ERROR(); RETURN_IF_NO_SECRETS_DB(false); SignonIdentityInfo info = metaDataDB->identity(id); if (info.isUserNameSecret()) { return secretsStorage->checkPassword(id, username, password); } else { return username == info.userName() && secretsStorage->checkPassword(id, QString(), password); } } SignonIdentityInfo CredentialsDB::credentials(const quint32 id, bool queryPassword) { TRACE() << "id:" << id << "queryPassword:" << queryPassword; INIT_ERROR(); SignonIdentityInfo info = metaDataDB->identity(id); if (queryPassword && !info.isNew()) { QString username, password; if (info.storePassword() && isSecretsDBOpen()) { TRACE() << "Loading credentials from DB."; secretsStorage->loadCredentials(id, username, password); } else { TRACE() << "Looking up credentials from cache."; m_secretsCache->lookupCredentials(id, username, password); } if (info.isUserNameSecret()) info.setUserName(username); info.setPassword(password); #ifdef DEBUG_ENABLED if (password.isEmpty()) { TRACE() << "Password is empty"; } #endif } return info; } QList CredentialsDB::credentials(const QMap &filter) { INIT_ERROR(); return metaDataDB->identities(filter); } quint32 CredentialsDB::insertCredentials(const SignonIdentityInfo &info) { SignonIdentityInfo newInfo = info; if (!info.isNew()) newInfo.setNew(); return updateCredentials(newInfo); } quint32 CredentialsDB::updateCredentials(const SignonIdentityInfo &info) { INIT_ERROR(); quint32 id = metaDataDB->updateIdentity(info); if (id == 0) return id; if (info.hasSecrets()) { QString password = info.password(); QString userName; if (info.isUserNameSecret()) userName = info.userName(); if (info.storePassword() && isSecretsDBOpen()) { secretsStorage->updateCredentials(id, userName, password); } else { /* Cache username and password in memory */ m_secretsCache->updateCredentials(id, userName, password, info.storePassword()); } } Q_EMIT credentialsUpdated(id); return id; } bool CredentialsDB::removeCredentials(const quint32 id) { INIT_ERROR(); /* We don't allow removing the credentials if the secrets DB is not * available */ RETURN_IF_NO_SECRETS_DB(false); return secretsStorage->removeCredentials(id) && metaDataDB->removeIdentity(id); } bool CredentialsDB::clear() { TRACE(); INIT_ERROR(); /* We don't allow clearing the DB if the secrets DB is not available */ RETURN_IF_NO_SECRETS_DB(false); return secretsStorage->clear() && metaDataDB->clear(); } QVariantMap CredentialsDB::loadData(const quint32 id, const QString &method) { TRACE() << "Loading:" << id << "," << method; INIT_ERROR(); if (id == 0) return QVariantMap(); quint32 methodId = metaDataDB->methodId(method); if (methodId == 0) return QVariantMap(); if (isSecretsDBOpen()) { return secretsStorage->loadData(id, methodId); } else { TRACE() << "Looking up data from cache"; return m_secretsCache->lookupData(id, methodId); } } bool CredentialsDB::storeData(const quint32 id, const QString &method, const QVariantMap &data) { TRACE() << "Storing:" << id << "," << method; INIT_ERROR(); if (id == 0) return false; quint32 methodId = metaDataDB->methodId(method); if (methodId == 0) { bool ok = false; methodId = metaDataDB->insertMethod(method, &ok); if (!ok) return false; } if (isSecretsDBOpen()) { return secretsStorage->storeData(id, methodId, data); } else { TRACE() << "Storing data into cache"; m_secretsCache->updateData(id, methodId, data); return true; } } bool CredentialsDB::removeData(const quint32 id, const QString &method) { TRACE() << "Removing:" << id << "," << method; INIT_ERROR(); RETURN_IF_NO_SECRETS_DB(false); if (id == 0) return false; quint32 methodId; if (!method.isEmpty()) { methodId = metaDataDB->methodId(method); if (methodId == 0) return false; } else { methodId = 0; } return secretsStorage->removeData(id, methodId); } QStringList CredentialsDB::accessControlList(const quint32 identityId) { INIT_ERROR(); return metaDataDB->accessControlList(identityId); } QStringList CredentialsDB::ownerList(const quint32 identityId) { INIT_ERROR(); return metaDataDB->ownerList(identityId); } QString CredentialsDB::credentialsOwnerSecurityToken(const quint32 identityId) { //return first owner token QStringList owners = ownerList(identityId); return owners.count() ? owners.at(0) : QString(); } bool CredentialsDB::addReference(const quint32 id, const QString &token, const QString &reference) { INIT_ERROR(); return metaDataDB->addReference(id, token, reference); } bool CredentialsDB::removeReference(const quint32 id, const QString &token, const QString &reference) { INIT_ERROR(); return metaDataDB->removeReference(id, token, reference); } QStringList CredentialsDB::references(const quint32 id, const QString &token) { INIT_ERROR(); return metaDataDB->references(id, token); } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/credentialsdb.h0000664000175000017500000001064114615454535022265 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @file credentialsdb.h * Definition of the CredentialsDB object. * @ingroup Accounts_and_SSO_Framework */ #ifndef CREDENTIALS_DB_H #define CREDENTIALS_DB_H #include #include #include "SignOn/abstract-secrets-storage.h" #define SSO_MAX_TOKEN_STORAGE (4*1024) // 4 kB for token store/identity/method class TestDatabase; namespace SignonDaemonNS { /*! * @enum IdentityFlags * Flags to be stored into database */ enum IdentityFlags { Validated = 0x0001, RememberPassword = 0x0002, UserNameIsSecret = 0x0004, }; class MetaDataDB; class SecretsCache; class SignonIdentityInfo; /*! * @class CredentialsDB * Manages the credentials I/O. * @ingroup Accounts_and_SSO_Framework */ class CredentialsDB: public QObject { Q_OBJECT Q_DISABLE_COPY(CredentialsDB) friend class ::TestDatabase; class ErrorMonitor { public: /* The constructor clears the errors in CredentialsDB, MetaDataDB and * SecretsDB. */ ErrorMonitor(CredentialsDB *db); /* The destructor collects the errors and sets * CredentialsDB::_lastError to the appropriate value. */ ~ErrorMonitor(); private: CredentialsDB *_db; }; friend class ErrorMonitor; public: CredentialsDB(const QString &metaDataDbName, SignOn::AbstractSecretsStorage *secretsStorage); ~CredentialsDB(); bool init(); /*! * This method will open the DB file containing the user secrets. * If this method is not called, or if it fails, the secrets will not be * available. */ bool openSecretsDB(const QString &secretsDbName); bool isSecretsDBOpen(); void closeSecretsDB(); SignOn::CredentialsDBError lastError() const; bool errorOccurred() const { return lastError().isValid(); }; QStringList methods(const quint32 id, const QString &securityToken = QString()); bool checkPassword(const quint32 id, const QString &username, const QString &password); SignonIdentityInfo credentials(const quint32 id, bool queryPassword = true); QList credentials(const QMap &filter); quint32 insertCredentials(const SignonIdentityInfo &info); quint32 updateCredentials(const SignonIdentityInfo &info); bool removeCredentials(const quint32 id); bool clear(); QStringList accessControlList(const quint32 identityId); QStringList ownerList(const quint32 identityId); QString credentialsOwnerSecurityToken(const quint32 identityId); QVariantMap loadData(const quint32 id, const QString &method); bool storeData(const quint32 id, const QString &method, const QVariantMap &data); bool removeData(const quint32 id, const QString &method = QString()); bool addReference(const quint32 id, const QString &token, const QString &reference); bool removeReference(const quint32 id, const QString &token, const QString &reference = QString()); QStringList references(const quint32 id, const QString &token = QString()); Q_SIGNALS: void credentialsUpdated(quint32 id); private: SignOn::AbstractSecretsStorage *secretsStorage; SecretsCache *m_secretsCache; MetaDataDB *metaDataDB; SignOn::CredentialsDBError _lastError; SignOn::CredentialsDBError noSecretsDB; }; } // namespace SignonDaemonNS #endif // CREDENTIALSDB_H signond-nicolasfella/src/signond/credentialsdb_p.h0000664000175000017500000002030214615454535022577 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef CREDENTIALS_DB_P_H #define CREDENTIALS_DB_P_H #include #include #include "SignOn/abstract-secrets-storage.h" #include "signonidentityinfo.h" #define SSO_METADATADB_VERSION 2 #define SSO_SECRETSDB_VERSION 1 class TestDatabase; namespace SignonDaemonNS { /*! * @class SecretsCache * Caches credentials or BLOB authentication data. */ class SecretsCache { friend class ::TestDatabase; public: class AuthCache { friend class SecretsCache; private: QString m_username; QString m_password; bool m_storePassword; QHash m_blobData; }; SecretsCache() {}; ~SecretsCache() {}; bool lookupCredentials(quint32 id, QString &username, QString &password) const; QVariantMap lookupData(quint32 id, quint32 method) const; void updateCredentials(quint32 id, const QString &username, const QString &password, bool storePassword); void updateData(quint32 id, quint32 method, const QVariantMap &data); void storeToDB(SignOn::AbstractSecretsStorage *secretsStorage) const; void clear(); private: QHash m_cache; }; /*! * @class SqlDatabase * Will be used manage the SQL database interaction. * @ingroup Accounts_and_SSO_Framework */ class SqlDatabase { friend class ::TestDatabase; public: /*! * Constructs a SqlDatabase object using the given hostname. * @param hostname */ SqlDatabase(const QString &hostname, const QString &connectionName, int version); /*! * Destroys the SqlDatabase object, closing the database connection. */ virtual ~SqlDatabase(); /*! * Connects to the DB and if necessary creates the tables */ bool init(); virtual bool createTables() = 0; virtual bool clear() = 0; virtual bool updateDB(int version); /*! * Creates the database connection. * @returns true if successful, false otherwise. */ bool connect(); /*! * Destroys the database connection. */ void disconnect(); bool startTransaction(); bool commit(); void rollback(); /*! * @returns true if database connection is opened, false otherwise. */ bool connected() { return m_database.isOpen(); } /*! * Sets the database name. * @param databseName */ void setDatabaseName(const QString &databaseName) { m_database.setDatabaseName(databaseName); } /*! * Sets the username for the database connection. * @param username */ void setUsername(const QString &username) { m_database.setUserName(username); } /*! * Sets the password for the database connection. * @param password */ void setPassword(const QString &password) { m_database.setPassword(password); } /*! * @returns the database name. */ QString databaseName() const { return m_database.databaseName(); } /*! * @returns the username for the database connection. */ QString username() const { return m_database.userName(); } /*! * @returns the password for the database connection. */ QString password() const { return m_database.password(); } QSqlQuery newQuery() const { return QSqlQuery(m_database); } /*! * Executes a specific database query. * If an error occurres the lastError() method can be used for handling * decissions. * @param query, the query string. * @returns the resulting sql query, which can be process in the case of a * 'SELECT' statement. */ QSqlQuery exec(const QString &query); /*! * Executes a specific database query. * If an error occurres the lastError() method can be used for handling * decissions. * @param query, the query. * @returns the resulting sql query, which can be process in the case of a * 'SELECT' statement. */ QSqlQuery exec(QSqlQuery &query); /*! * Executes a specific database set of queryes (INSERTs, UPDATEs, DELETEs) * in a transaction context (No nested transactions supported - sqlite * reasons). * If an error occurres the lastError() method can be used for handling * decissions. * @param queryList, the query list to be executed. * @returns true if the transaction commits successfully, false otherwise. */ bool transactionalExec(const QStringList &queryList); /*! * @returns true, if the database has any tables created, false otherwise. */ bool hasTables() const { return m_database.tables().count() > 0 ? true : false; } /*! * @returns a list of the supported drivers on the specific OS. */ static QStringList supportedDrivers() { return QSqlDatabase::drivers(); } /*! * @returns the last occurred error if any. If not error occurred on the * last performed operation the error object is invalid. */ SignOn::CredentialsDBError lastError() const; bool errorOccurred() const { return lastError().isValid(); }; void clearError() { m_lastError.clear(); } /*! * Serializes a SQL error into a string. * @param error, method will fail if an error object is passed. * @returns the error information as string. */ static QString errorInfo(const QSqlError &error); QString connectionName() const { return m_database.connectionName(); } protected: QStringList queryList(const QString &query_str); QStringList queryList(QSqlQuery &query); void setLastError(const QSqlError &sqlError); private: SignOn::CredentialsDBError m_lastError; protected: int m_version; QSqlDatabase m_database; friend class CredentialsDB; }; class MetaDataDB: public SqlDatabase { friend class ::TestDatabase; public: MetaDataDB(const QString &name): SqlDatabase(name, QLatin1String("SSO-metadata"), SSO_METADATADB_VERSION) {} bool createTables(); bool updateDB(int version); QStringList methods(const quint32 id, const QString &securityToken = QString()); quint32 insertMethod(const QString &method, bool *ok = 0); quint32 methodId(const QString &method); SignonIdentityInfo identity(const quint32 id); QList identities(const QMap &filter); quint32 updateIdentity(const SignonIdentityInfo &info); bool removeIdentity(const quint32 id); bool clear(); QStringList accessControlList(const quint32 identityId); QStringList ownerList(const quint32 identityId); bool addReference(const quint32 id, const QString &token, const QString &reference); bool removeReference(const quint32 id, const QString &token, const QString &reference = QString()); QStringList references(const quint32 id, const QString &token = QString()); private: bool insertMethods(QMap methods); quint32 updateCredentials(const SignonIdentityInfo &info); bool updateRealms(quint32 id, const QStringList &realms, bool isNew); QStringList tableUpdates2(); }; } // namespace SignonDaemonNS #endif // CREDENTIALSDB_P_H signond-nicolasfella/src/signond/default-crypto-manager.cpp0000664000175000017500000000263614615454535024374 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "default-crypto-manager.h" using namespace SignonDaemonNS; DefaultCryptoManager::DefaultCryptoManager(QObject *parent): AbstractCryptoManager(parent) { } DefaultCryptoManager::~DefaultCryptoManager() { } bool DefaultCryptoManager::initialize(const QVariantMap &configuration) { m_storagePath = configuration.value(QLatin1String("StoragePath")).toString(); setFileSystemSetup(true); setFileSystemMounted(true); return true; } QString DefaultCryptoManager::fileSystemMountPath() const { return m_storagePath; } signond-nicolasfella/src/signond/default-crypto-manager.h0000664000175000017500000000351014615454535024031 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @file cryptomanager.h * Definition of the DefaultCryptoManager object. * @ingroup Accounts_and_SSO_Framework */ #ifndef SIGNON_DEFAULT_CRYPTO_MANAGER_H #define SIGNON_DEFAULT_CRYPTO_MANAGER_H #include "SignOn/abstract-crypto-manager.h" #include namespace SignonDaemonNS { /*! * @class DefaultCryptoManager * Dummy implementation of a manager for the credentials storage file system * encryption. * It always reports that the file system is mounted, without actually doing * anything. * @ingroup Accounts_and_SSO_Framework */ class DefaultCryptoManager: public SignOn::AbstractCryptoManager { Q_OBJECT public: explicit DefaultCryptoManager(QObject *parent = 0); ~DefaultCryptoManager(); /* reimplemented virtual methods */ virtual bool initialize(const QVariantMap &configuration); QString fileSystemMountPath() const; private: QString m_storagePath; }; } //namespace #endif // SIGNON_DEFAULT_CRYPTO_MANAGER_H signond-nicolasfella/src/signond/default-key-authorizer.cpp0000664000175000017500000000270214615454535024420 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "default-key-authorizer.h" using namespace SignonDaemonNS; DefaultKeyAuthorizer::DefaultKeyAuthorizer(SignOn::KeyHandler *keyHandler, QObject *parent): AbstractKeyAuthorizer(keyHandler, parent) { } DefaultKeyAuthorizer::~DefaultKeyAuthorizer() { } void DefaultKeyAuthorizer::queryKeyAuthorization(const SignOn::Key &key, Reason reason) { Q_UNUSED(reason); int result = keyHandler()->canAddKeyAuthorization() ? Approved : Exclusive; emit keyAuthorizationQueried(key, result); } signond-nicolasfella/src/signond/default-key-authorizer.h0000664000175000017500000000315414615454535024067 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @copyright Copyright (C) 2011 Nokia Corporation. * @license LGPL */ #ifndef SIGNON_DEFAULT_KEY_AUTHORIZER_H #define SIGNON_DEFAULT_KEY_AUTHORIZER_H #include "SignOn/AbstractKeyAuthorizer" #include namespace SignonDaemonNS { /*! * @class DefaultKeyAuthorizer * * Implements a default key authorizer, which authorizes all given keys. */ class DefaultKeyAuthorizer: public SignOn::AbstractKeyAuthorizer { Q_OBJECT public: explicit DefaultKeyAuthorizer(SignOn::KeyHandler *keyHandler, QObject *parent = 0); ~DefaultKeyAuthorizer(); /* reimplemented from KeyAuthorizer */ void queryKeyAuthorization(const SignOn::Key &key, Reason reason); }; } // namespace #endif // SIGNON_DEFAULT_KEY_AUTHORIZER_H signond-nicolasfella/src/signond/default-secrets-storage.cpp0000664000175000017500000002427314615454535024557 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "default-secrets-storage.h" #include "signond-common.h" #define RETURN_IF_NOT_OPEN(retval) \ if (!isOpen()) { \ TRACE() << "Secrets DB is not available"; \ SignOn::CredentialsDBError error(QLatin1String("Not open"), \ SignOn::CredentialsDBError::NotOpen); \ setLastError(error); return retval; \ } #define S(s) QLatin1String(s) using namespace SignonDaemonNS; bool SecretsDB::createTables() { QStringList createTableQuery = QStringList() << QString::fromLatin1( "CREATE TABLE CREDENTIALS" "(id INTEGER NOT NULL UNIQUE," "username TEXT," "password TEXT," "PRIMARY KEY (id))") << QString::fromLatin1( "CREATE TABLE STORE" "(identity_id INTEGER," "method_id INTEGER," "key TEXT," "value BLOB," "PRIMARY KEY (identity_id, method_id, key))") << QString::fromLatin1( // Cascading Delete "CREATE TRIGGER tg_delete_credentials " "BEFORE DELETE ON CREDENTIALS " "FOR EACH ROW BEGIN " " DELETE FROM STORE WHERE STORE.identity_id = OLD.id; " "END; " ); foreach (QString createTable, createTableQuery) { QSqlQuery query = exec(createTable); if (lastError().isValid()) { TRACE() << "Error occurred while creating the database."; return false; } query.clear(); commit(); } return true; } bool SecretsDB::clear() { TRACE(); QStringList clearCommands = QStringList() << QLatin1String("DELETE FROM CREDENTIALS") << QLatin1String("DELETE FROM STORE"); return transactionalExec(clearCommands); } bool SecretsDB::updateCredentials(const quint32 id, const QString &username, const QString &password) { if (!startTransaction()) { TRACE() << "Could not start transaction. Error inserting credentials."; return false; } QSqlQuery query = newQuery(); TRACE() << "INSERT:" << id; query.prepare(S("INSERT OR REPLACE INTO CREDENTIALS " "(id, username, password) " "VALUES(:id, :username, :password)")); query.bindValue(S(":id"), id); query.bindValue(S(":username"), username); query.bindValue(S(":password"), password); exec(query); if (errorOccurred()) { rollback(); TRACE() << "Error occurred while storing crendentials"; return false; } return commit(); } bool SecretsDB::removeCredentials(const quint32 id) { TRACE(); QStringList queries = QStringList() << QString::fromLatin1( "DELETE FROM CREDENTIALS WHERE id = %1").arg(id) << QString::fromLatin1( "DELETE FROM STORE WHERE identity_id = %1").arg(id); return transactionalExec(queries); } bool SecretsDB::loadCredentials(const quint32 id, QString &username, QString &password) { TRACE(); QString queryStr = QString::fromLatin1("SELECT username, password FROM credentials " "WHERE id = %1").arg(id); QSqlQuery query = exec(queryStr); if (!query.first()) { TRACE() << "No result or invalid credentials query."; return false; } username = query.value(0).toString(); password = query.value(1).toString(); return true; } QVariantMap SecretsDB::loadData(quint32 id, quint32 method) { TRACE(); QSqlQuery q = newQuery(); q.prepare(S("SELECT key, value " "FROM STORE WHERE identity_id = :id AND method_id = :method")); q.bindValue(S(":id"), id); q.bindValue(S(":method"), method); exec(q); if (errorOccurred()) return QVariantMap(); QVariantMap result; while (q.next()) { QByteArray array; array = q.value(1).toByteArray(); QDataStream stream(array); QVariant data; stream >> data; result.insert(q.value(0).toString(), data); } return result; } bool SecretsDB::storeData(quint32 id, quint32 method, const QVariantMap &data) { TRACE(); if (!startTransaction()) { TRACE() << "Could not start transaction. Error inserting data."; return false; } /* first, remove existing data */ QSqlQuery q = newQuery(); q.prepare(S("DELETE FROM STORE WHERE identity_id = :id " "AND method_id = :method")); q.bindValue(S(":id"), id); q.bindValue(S(":method"), method); exec(q); if (errorOccurred()) { rollback(); TRACE() << "Data removal failed."; return false; } bool allOk = true; qint32 dataCounter = 0; if (!(data.keys().empty())) { QMapIterator it(data); while (it.hasNext()) { it.next(); QByteArray array; QDataStream stream(&array, QIODevice::WriteOnly); stream << it.value(); dataCounter += it.key().size() +array.size(); if (dataCounter >= SSO_MAX_TOKEN_STORAGE) { BLAME() << "storing data max size exceeded"; allOk = false; break; } /* Key/value insert/replace/delete */ QSqlQuery query = newQuery(); if (!it.value().isValid() || it.value().isNull()) { continue; } TRACE() << "insert"; query.prepare(S( "INSERT OR REPLACE INTO STORE " "(identity_id, method_id, key, value) " "VALUES(:id, :method, :key, :value)")); query.bindValue(S(":value"), array); query.bindValue(S(":id"), id); query.bindValue(S(":method"), method); query.bindValue(S(":key"), it.key()); exec(query); if (errorOccurred()) { allOk = false; break; } } } if (allOk && commit()) { TRACE() << "Data insertion ok."; return true; } rollback(); TRACE() << "Data insertion failed."; return false; } bool SecretsDB::removeData(quint32 id, quint32 method) { TRACE(); if (!startTransaction()) { TRACE() << "Could not start transaction. Error removing data."; return false; } QSqlQuery q = newQuery(); if (method == 0) { q.prepare(S("DELETE FROM STORE WHERE identity_id = :id")); } else { q.prepare(S("DELETE FROM STORE WHERE identity_id = :id " "AND method_id = :method")); q.bindValue(S(":method"), method); } q.bindValue(S(":id"), id); exec(q); if (!errorOccurred() && commit()) { TRACE() << "Data removal ok."; return true; } else { rollback(); TRACE() << "Data removal failed."; return false; } } DefaultSecretsStorage::DefaultSecretsStorage(QObject *parent): AbstractSecretsStorage(parent), m_secretsDB(0) { } DefaultSecretsStorage::~DefaultSecretsStorage() { close(); } bool DefaultSecretsStorage::initialize(const QVariantMap &configuration) { if (isOpen()) { TRACE() << "Initializing open DB; closing first..."; close(); } QString name; // force deep copy / detach name.append(configuration.value(QLatin1String("name")).toString()); m_secretsDB = new SecretsDB(name); if (!m_secretsDB->init()) { setLastError(m_secretsDB->lastError()); delete m_secretsDB; m_secretsDB = 0; return false; } m_secretsDBConnectionName.clear(); m_secretsDBConnectionName.append(m_secretsDB->connectionName()); setIsOpen(true); return true; } bool DefaultSecretsStorage::close() { if (m_secretsDB != 0) { delete m_secretsDB; QSqlDatabase::removeDatabase(m_secretsDBConnectionName); m_secretsDB = 0; } return AbstractSecretsStorage::close(); } bool DefaultSecretsStorage::clear() { RETURN_IF_NOT_OPEN(false); return m_secretsDB->clear(); } bool DefaultSecretsStorage::updateCredentials(const quint32 id, const QString &username, const QString &password) { RETURN_IF_NOT_OPEN(false); return m_secretsDB->updateCredentials(id, username, password); } bool DefaultSecretsStorage::removeCredentials(const quint32 id) { RETURN_IF_NOT_OPEN(false); return m_secretsDB->removeCredentials(id); } bool DefaultSecretsStorage::loadCredentials(const quint32 id, QString &username, QString &password) { RETURN_IF_NOT_OPEN(false); return m_secretsDB->loadCredentials(id, username, password); } QVariantMap DefaultSecretsStorage::loadData(quint32 id, quint32 method) { RETURN_IF_NOT_OPEN(QVariantMap()); return m_secretsDB->loadData(id, method); } bool DefaultSecretsStorage::storeData(quint32 id, quint32 method, const QVariantMap &data) { RETURN_IF_NOT_OPEN(false); return m_secretsDB->storeData(id, method, data); } bool DefaultSecretsStorage::removeData(quint32 id, quint32 method) { RETURN_IF_NOT_OPEN(false); return m_secretsDB->removeData(id, method); } signond-nicolasfella/src/signond/default-secrets-storage.h0000664000175000017500000000631114615454535024215 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2011-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ /*! * @file secrets-storage.h * Definition of the DefaultSecretsStorage object. * @ingroup Accounts_and_SSO_Framework */ #ifndef SIGNON_DEFAULT_SECRETS_STORAGE_H #define SIGNON_DEFAULT_SECRETS_STORAGE_H #include "SignOn/abstract-secrets-storage.h" #include "credentialsdb.h" #include "credentialsdb_p.h" #include namespace SignonDaemonNS { class SecretsDB: public SqlDatabase { friend class ::TestDatabase; public: SecretsDB(const QString &name): SqlDatabase(name, QLatin1String("SSO-secrets"), SSO_SECRETSDB_VERSION) {} bool createTables(); bool clear(); bool updateCredentials(const quint32 id, const QString &username, const QString &password); bool removeCredentials(const quint32 id); bool loadCredentials(const quint32 id, QString &username, QString &password); QVariantMap loadData(quint32 id, quint32 method); bool storeData(quint32 id, quint32 method, const QVariantMap &data); bool removeData(quint32 id, quint32 method); }; /*! * @class DefaultSecretsStorage * SQLite-based implementation of the AbstractSecretsStorage interface. The * secrets are stored in a SQLite DB, unencrypted. To achieve encryption, you * can pair this class with a CryptoManager which provide an encrypted * filesystem. * @ingroup Accounts_and_SSO_Framework */ class DefaultSecretsStorage: public SignOn::AbstractSecretsStorage { Q_OBJECT public: explicit DefaultSecretsStorage(QObject *parent = 0); ~DefaultSecretsStorage(); /* reimplemented virtual methods */ bool initialize(const QVariantMap &configuration); bool close(); bool clear(); bool updateCredentials(const quint32 id, const QString &username, const QString &password); bool removeCredentials(const quint32 id); bool loadCredentials(const quint32 id, QString &username, QString &password); QVariantMap loadData(quint32 id, quint32 method); bool storeData(quint32 id, quint32 method, const QVariantMap &data); bool removeData(quint32 id, quint32 method); private: SecretsDB *m_secretsDB; QString m_secretsDBConnectionName; }; } //namespace #endif // SIGNON_DEFAULT_SECRETS_STORAGE_H signond-nicolasfella/src/signond/error.h0000664000175000017500000000456414615454535020622 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2020 UBports Foundation * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNOND_ERROR_H #define SIGNOND_ERROR_H #include namespace SignonDaemonNS { class Error { public: enum Code { NoError = 0, UnknownError, InternalServer, InternalCommunication, PermissionDenied, MethodOrMechanismNotAllowed, EncryptionFailed, MethodNotKnown, ServiceNotAvailable, InvalidQuery, MethodNotAvailable, IdentityNotFound, StoreFailed, RemoveFailed, SignoutFailed, OperationCanceled, CredentialsNotAvailable, ReferenceNotFound, MechanismNotAvailable, MissingData, InvalidCredentials, NotAuthorized, WrongState, OperationNotSupported, NoConnection, NetworkError, SslError, RuntimeError, SessionCanceled, TimedOut, UserInteraction, OperationFailed, TOSNotAccepted, ForgotPassword, IncorrectDate, UserDefinedError, }; Error(Code code = NoError, const QString &message = QString()): m_code(code), m_message(message) { } static Error none() { return Error(NoError); } operator bool() const { return isError(); } bool isError() const { return m_code != Code::NoError; } Code code() const { return m_code; } QString message() const { return m_message; } private: Code m_code; QString m_message; }; } // namespace SignonDaemonNS #endif // SIGNOND_ERROR_H signond-nicolasfella/src/signond/erroradaptor.cpp0000664000175000017500000000607714615454535022531 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2020 UBports Foundation * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "erroradaptor.h" #include "signond-common.h" using namespace SignonDaemonNS; #define DECLARE_ERROR(s) \ { SIGNOND_##s##_ERR_NAME, SIGNOND_##s##_ERR_STR } static struct ErrorStrings { QString code; QString defaultMessage; } s_errorStrings[] = { // These must be kept in sync with the Error::Code from the header file { QStringLiteral(), QStringLiteral() }, DECLARE_ERROR(UNKNOWN), DECLARE_ERROR(INTERNAL_SERVER), DECLARE_ERROR(INTERNAL_COMMUNICATION), DECLARE_ERROR(PERMISSION_DENIED), DECLARE_ERROR(METHOD_OR_MECHANISM_NOT_ALLOWED), DECLARE_ERROR(ENCRYPTION_FAILED), DECLARE_ERROR(METHOD_NOT_KNOWN), DECLARE_ERROR(SERVICE_NOT_AVAILABLE), DECLARE_ERROR(INVALID_QUERY), DECLARE_ERROR(METHOD_NOT_AVAILABLE), DECLARE_ERROR(IDENTITY_NOT_FOUND), DECLARE_ERROR(STORE_FAILED), DECLARE_ERROR(REMOVE_FAILED), DECLARE_ERROR(SIGNOUT_FAILED), DECLARE_ERROR(IDENTITY_OPERATION_CANCELED), DECLARE_ERROR(CREDENTIALS_NOT_AVAILABLE), DECLARE_ERROR(REFERENCE_NOT_FOUND), DECLARE_ERROR(MECHANISM_NOT_AVAILABLE), DECLARE_ERROR(MISSING_DATA), DECLARE_ERROR(INVALID_CREDENTIALS), DECLARE_ERROR(NOT_AUTHORIZED), DECLARE_ERROR(WRONG_STATE), DECLARE_ERROR(OPERATION_NOT_SUPPORTED), DECLARE_ERROR(NO_CONNECTION), DECLARE_ERROR(NETWORK), DECLARE_ERROR(SSL), DECLARE_ERROR(RUNTIME), DECLARE_ERROR(SESSION_CANCELED), DECLARE_ERROR(TIMED_OUT), DECLARE_ERROR(USER_INTERACTION), DECLARE_ERROR(OPERATION_FAILED), DECLARE_ERROR(TOS_NOT_ACCEPTED), DECLARE_ERROR(FORGOT_PASSWORD), DECLARE_ERROR(INCORRECT_DATE), { SIGNOND_USER_ERROR_ERR_NAME, QString() }, // plugin-defined errors }; ErrorAdaptor::ErrorAdaptor(const Error &error) { static constexpr size_t numErrors = sizeof(s_errorStrings) / sizeof(ErrorStrings); Error::Code errorCode = error.code(); QString errorMessage = error.message(); if (errorCode > Error::NoError && errorCode < numErrors) { m_code = s_errorStrings[errorCode].code; m_message = errorMessage.isEmpty() ? s_errorStrings[errorCode].defaultMessage : errorMessage; } else { BLAME() << "Unhandled error code:" << errorCode; } } signond-nicolasfella/src/signond/erroradaptor.h0000664000175000017500000000264114615454535022167 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2020 UBports Foundation * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNOND_ERROR_ADAPTOR_H #define SIGNOND_ERROR_ADAPTOR_H #include "error.h" #include namespace SignonDaemonNS { class ErrorAdaptor { public: explicit ErrorAdaptor(const Error &error); QString code() const { return m_code; } QString message() const { return m_message; } QDBusMessage createReply(const QDBusMessage &msg) const { return msg.createErrorReply(m_code, m_message); } private: QString m_code; QString m_message; }; } // namespace SignonDaemonNS #endif // SIGNOND_ERROR_ADAPTOR_H signond-nicolasfella/src/signond/main.cpp0000664000175000017500000000272014615454535020740 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signondaemon.h" #include using namespace SignonDaemonNS; void installSigHandlers() { struct sigaction act; act.sa_handler = SignonDaemon::signalHandler; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; sigaction(SIGHUP, &act, 0); sigaction(SIGTERM, &act, 0); sigaction(SIGINT, &act, 0); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); installSigHandlers(); QMetaObject::invokeMethod(SignonDaemon::instance(), "init", Qt::QueuedConnection); return app.exec(); } signond-nicolasfella/src/signond/peercontext.h0000664000175000017500000000351214615454535022021 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2020 UBports Foundation * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNOND_PEER_CONTEXT_H #define SIGNOND_PEER_CONTEXT_H #include #include #include namespace SignonDaemonNS { class AccessControlManagerHelper; class PeerContext { public: PeerContext(const QDBusConnection &connection, const QDBusMessage &message): m_connection(connection), m_message(message) { } PeerContext(const QDBusContext &context): m_connection(context.connection()), m_message(context.message()) { } protected: /* Keeping the members protected ensures that we don't accidentally use * them to deliver replies. */ const QDBusConnection &connection() const { return m_connection; } const QDBusMessage &message() const { return m_message; } private: friend AccessControlManagerHelper; QDBusConnection m_connection; QDBusMessage m_message; }; } // namespace SignonDaemonNS #endif // SIGNOND_PEER_CONTEXT_H signond-nicolasfella/src/signond/pluginproxy.h0000664000175000017500000000656214615454535022071 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef PLUGINPROXY_H #define PLUGINPROXY_H #include #include #include namespace SignOn { class BlobIOHandler; class EncryptedDevice; }; namespace SignonDaemonNS { /*! * @class PluginProcess * Process to run authentication. * @todo description. */ class PluginProcess: public QProcess { Q_OBJECT friend class PluginProxy; PluginProcess(QObject* parent = NULL); ~PluginProcess(); }; /*! * @class PluginProxy * Plugin proxy. * @todo description. */ class PluginProxy: public QObject { Q_OBJECT friend class SignonIdentity; friend class TestAuthSession; public: static PluginProxy *createNewPluginProxy(const QString &type); virtual ~PluginProxy(); bool restartIfRequired(); bool isProcessing(); public Q_SLOTS: QString type() const { return m_type; } QStringList mechanisms() const { return m_mechanisms; } bool process(const QVariantMap &inData, const QString &mechanism); bool processUi(const QVariantMap &inData); bool processRefresh(const QVariantMap &inData); void cancel(); void stop(); Q_SIGNALS: void processResultReply(const QVariantMap &data); void processStore(const QVariantMap &data); void processUiRequest(const QVariantMap &data); void processRefreshRequest(const QVariantMap &data); void processError(int error, const QString &message); void stateChanged(int state, const QString &message); private: QString queryType(); QStringList queryMechanisms(); bool waitForStarted(int timeout); bool waitForFinished(int timeout); bool readOnReady(QByteArray &buffer, int timeout); void handlePluginResponse(const quint32 resultOperation, const QVariantMap &sessionDataMap = QVariantMap()); bool isResultOperationCodeValid(const int opCode) const; private Q_SLOTS: void onReadStandardOutput(); void onReadStandardError(); void onExit(int exitCode, QProcess::ExitStatus exitStatus); void onError(QProcess::ProcessError err); void sessionDataReceived(const QVariantMap &map); void blobIOError(); private: PluginProxy(QString type, QObject *parent = NULL); bool m_isProcessing; bool m_isResultObtained; QString m_type; QStringList m_mechanisms; int m_uiPolicy; int m_currentResultOperation; PluginProcess *m_process; SignOn::BlobIOHandler *m_blobIOHandler; }; } //namespace SignonDaemonNS #endif /* PLUGINPROXY_H */ signond-nicolasfella/src/signond/signonauthsession.cpp0000664000175000017500000000727214615454535023606 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signond-common.h" #include "signonauthsession.h" using namespace SignonDaemonNS; SignonAuthSession::SignonAuthSession(SignonSessionCore *core, pid_t ownerPid): QObject(core), m_ownerPid(ownerPid) { TRACE(); static quint32 incr = 0; QString objectName = SIGNOND_DAEMON_OBJECTPATH + QLatin1String("/AuthSession_") + QString::number(incr++, 16); TRACE() << objectName; setObjectName(objectName); connect(core, SIGNAL(stateChanged(const QString&, int, const QString&)), this, SLOT(stateChangedSlot(const QString&, int, const QString&))); } SignonAuthSession::~SignonAuthSession() { Q_EMIT unregistered(); TRACE(); } SignonAuthSession *SignonAuthSession::createAuthSession(const quint32 id, const QString &method, SignonDaemon *parent, pid_t ownerPid) { TRACE(); SignonSessionCore *core = SignonSessionCore::sessionCore(id, method, parent); if (!core) { TRACE() << "Cannot retrieve proper tasks queue"; return NULL; } SignonAuthSession *sas = new SignonAuthSession(core, ownerPid); TRACE() << "SignonAuthSession created successfully:" << sas->objectName(); return sas; } void SignonAuthSession::stopAllAuthSessions() { SignonSessionCore::stopAllAuthSessions(); } quint32 SignonAuthSession::id() const { return parent()->id(); } QString SignonAuthSession::method() const { return parent()->method(); } pid_t SignonAuthSession::ownerPid() const { return m_ownerPid; } QStringList SignonAuthSession::queryAvailableMechanisms(const QStringList &wantedMechanisms) { return parent()->queryAvailableMechanisms(wantedMechanisms); } void SignonAuthSession::process(const QVariantMap &sessionDataVa, const QString &mechanism, const PeerContext &peerContext, const ProcessCb &callback) { parent()->process(peerContext, sessionDataVa, mechanism, objectName(), callback); } void SignonAuthSession::cancel() { TRACE(); parent()->cancel(objectName()); } void SignonAuthSession::setId(quint32 id) { parent()->setId(id); } void SignonAuthSession::objectUnref() { //TODO - remove the `objectUnref` functionality from the DBus API TRACE(); cancel(); deleteLater(); } void SignonAuthSession::stateChangedSlot(const QString &sessionKey, int state, const QString &message) { TRACE(); if (sessionKey == objectName()) emit stateChanged(state, message); } signond-nicolasfella/src/signond/signonauthsession.h0000664000175000017500000000572714615454535023256 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONAUTHSESSION_H_ #define SIGNONAUTHSESSION_H_ #include /* * TODO: remove invocation of plugin operations into the main signond process */ #include "signond-common.h" #include "signonsessioncore.h" #include using namespace SignOn; namespace SignonDaemonNS { class Error; class PeerContext; class SignonAuthSessionAdaptor; /*! * @class SignonAuthSession * Daemon side representation of authentication session. * @todo description. */ class SignonAuthSession: public QObject { Q_OBJECT public: inline SignonSessionCore *parent() const { return static_cast(QObject::parent()); } friend class SignonAuthSessionAdaptor; typedef SignonAuthSessionAdaptor Adaptor; static SignonAuthSession *createAuthSession(const quint32 id, const QString &method, SignonDaemon *parent, pid_t ownerPid); static void stopAllAuthSessions(); quint32 id() const; QString method() const; pid_t ownerPid() const; typedef std::function ProcessCb; public Q_SLOTS: QStringList queryAvailableMechanisms(const QStringList &wantedMechanisms); void process(const QVariantMap &sessionDataVa, const QString &mechanism, const PeerContext &peerContext, const ProcessCb &callback); void cancel(); void setId(quint32 id); void objectUnref(); Q_SIGNALS: void stateChanged(int state, const QString &message); void unregistered(); private Q_SLOTS: void stateChangedSlot(const QString &sessionKey, int state, const QString &message); protected: SignonAuthSession(SignonSessionCore *core, pid_t ownerPid); virtual ~SignonAuthSession(); private: quint32 m_id; QString m_method; pid_t m_ownerPid; Q_DISABLE_COPY(SignonAuthSession) }; //class SignonDaemon } //namespace SignonDaemonNS #endif //SIGNONAUTHSESSION_H_ signond-nicolasfella/src/signond/signonauthsessionadaptor.cpp0000664000175000017500000001507714615454535025163 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signonauthsessionadaptor.h" #include "accesscontrolmanagerhelper.h" #include "credentialsaccessmanager.h" #include "credentialsdb.h" #include "erroradaptor.h" namespace SignonDaemonNS { SignonAuthSessionAdaptor::SignonAuthSessionAdaptor(SignonAuthSession *parent): QObject(parent) { QObject::connect(parent, &SignonAuthSession::unregistered, this, &SignonAuthSessionAdaptor::unregistered); QObject::connect(parent, &SignonAuthSession::stateChanged, this, &SignonAuthSessionAdaptor::stateChanged); } SignonAuthSessionAdaptor::~SignonAuthSessionAdaptor() { } void SignonAuthSessionAdaptor::errorReply(const QString &name, const QString &message) { const QDBusContext &context = *this; QDBusMessage errReply = context.message().createErrorReply(name, message); context.connection().send(errReply); } QStringList SignonAuthSessionAdaptor::queryAvailableMechanisms( const QStringList &wantedMechanisms) { TRACE(); QDBusContext &dbusContext = *this; if (AccessControlManagerHelper::pidOfPeer(dbusContext) != parent()->ownerPid()) { TRACE() << "queryAvailableMechanisms called from peer that doesn't " "own the AuthSession object\n"; QString errMsg; QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR << " Authentication session owned by other " "process."; errorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME, errMsg); return QStringList(); } return parent()->queryAvailableMechanisms(wantedMechanisms); } QVariantMap SignonAuthSessionAdaptor::process(const QVariantMap &sessionDataVa, const QString &mechanism) { TRACE() << mechanism; QString allowedMechanism(mechanism); if (parent()->id() != SIGNOND_NEW_IDENTITY) { CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if (db) { SignonIdentityInfo identityInfo = db->credentials(parent()->id(), false); if (!identityInfo.checkMethodAndMechanism(parent()->method(), mechanism, allowedMechanism)) { QString errMsg; QTextStream(&errMsg) << SIGNOND_METHOD_OR_MECHANISM_NOT_ALLOWED_ERR_STR << " Method:" << parent()->method() << ", mechanism:" << mechanism << ", allowed:" << allowedMechanism; errorReply(SIGNOND_METHOD_OR_MECHANISM_NOT_ALLOWED_ERR_NAME, errMsg); return QVariantMap(); } } else { BLAME() << "Null database handler object."; } } QDBusContext &dbusContext = *this; QDBusConnection connection = dbusContext.connection(); const QDBusMessage &message = dbusContext.message(); if (AccessControlManagerHelper::pidOfPeer(dbusContext) != parent()->ownerPid()) { TRACE() << "process called from peer that doesn't own the AuthSession " "object"; QString errMsg; QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR << " Authentication session owned by other " "process."; errorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME, errMsg); return QVariantMap(); } auto callback = [this, connection, message](const QVariantMap &map, const Error &error) { if (!error) { QDBusMessage dbusreply = message.createReply(); dbusreply << map; connection.send(dbusreply); } else { connection.send(ErrorAdaptor(error).createReply(message)); } }; parent()->process(sessionDataVa, allowedMechanism, dbusContext, callback); dbusContext.setDelayedReply(true); return QVariantMap(); // ignored } void SignonAuthSessionAdaptor::cancel() { TRACE(); QDBusContext &dbusContext = *this; if (AccessControlManagerHelper::pidOfPeer(dbusContext) != parent()->ownerPid()) { TRACE() << "cancel called from peer that doesn't own the AuthSession " "object"; return; } parent()->cancel(); } void SignonAuthSessionAdaptor::setId(quint32 id) { TRACE(); QDBusContext &dbusContext = *this; if (AccessControlManagerHelper::pidOfPeer(PeerContext(dbusContext)) != parent()->ownerPid()) { TRACE() << "setId called from peer that doesn't own the AuthSession " "object"; return; } if (!AccessControlManagerHelper::instance()->isPeerAllowedToUseIdentity( PeerContext(dbusContext), id)) { TRACE() << "setId called with an identifier the peer is not allowed " "to use"; return; } parent()->setId(id); } void SignonAuthSessionAdaptor::objectUnref() { TRACE(); QDBusContext &dbusContext = *this; if (AccessControlManagerHelper::pidOfPeer(dbusContext) != parent()->ownerPid()) { TRACE() << "objectUnref called from peer that doesn't own the " "AuthSession object"; return; } parent()->objectUnref(); } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signonauthsessionadaptor.h0000664000175000017500000000377214615454535024627 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONAUTHSESSIONADAPTOR_H_ #define SIGNONAUTHSESSIONADAPTOR_H_ #include #include #include "signond-common.h" #include "signonauthsession.h" namespace SignonDaemonNS { class SignonAuthSessionAdaptor: public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "com.google.code.AccountsSSO.SingleSignOn.AuthSession") public: SignonAuthSessionAdaptor(SignonAuthSession *parent); virtual ~SignonAuthSessionAdaptor(); inline SignonAuthSession *parent() const { return static_cast(QObject::parent()); } private: void errorReply(const QString &name, const QString &message); public Q_SLOTS: QStringList queryAvailableMechanisms(const QStringList &wantedMechanisms); QVariantMap process(const QVariantMap &sessionDataVa, const QString &mechanism); Q_NOREPLY void cancel(); Q_NOREPLY void setId(quint32 id); Q_NOREPLY void objectUnref(); Q_SIGNALS: void stateChanged(int state, const QString &message); void unregistered(); }; } //namespace SignonDaemonNS #endif /* SIGNONAUTHSESSIONADAPTOR_H_ */ signond-nicolasfella/src/signond/signond-common.h0000664000175000017500000000352214615454535022411 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNOND_COMMON_H_ #define SIGNOND_COMMON_H_ #include "signond/signoncommon.h" #ifdef TRACE #undef TRACE #endif #ifdef BLAME #undef BLAME #endif #ifdef SIGNOND_TRACE #define SIGNON_TRACE #include "SignOn/Debug" #endif #ifdef TESTS_TRACE #define TRACE() \ qDebug() << __FILE__ << __LINE__ << __func__ #define BLAME() \ qCritical() << __FILE__ << __LINE__ << __func__ #endif /* * Idle timeout for remote identities and their plugin processes * */ #define SIGNOND_MAX_IDLE_TIME 300 /* * Signon UI DBUS defs * */ #define SIGNON_UI_SERVICE QLatin1String("com.nokia.singlesignonui") #define SIGNON_UI_DAEMON_OBJECTPATH QLatin1String("/SignonUi") /* * Signon Daemon default configuration values */ const char signonDefaultDbName[] = "signon.db"; const char signonDefaultSecretsDbName[] = "signon-secrets.db"; const bool signonDefaultUseEncryption = true; const char signonDefaultStoragePath[] = "~/.config/signond"; #endif // SIGNOND_COMMON_H_ signond-nicolasfella/src/signond/signond.conf0000664000175000017500000000341314615454535021620 0ustar coucoufcoucouf;Signon Daemon configuration file [General] ; Uncomment the StoragePath line to specify a location for the signon DB. ; If not given, uses $XDG_CONFIG_HOME/signond (or ~/.config/signond if ; the variable XDG_CONFIG_HOME is unset). ;StoragePath=~/.signon/ ;0 - fatal, 1 - critical (default), 2 - info/debug ;LoggingLevel=2 [SecureStorage] ; CryptoManager selects the encryption for the credentials FS. Possible values: ; "default" - no encryption ; "cryptsetup" - encrypted with the cryptsetup extension ; If omitted, the first extension plugin found to provide a suitable ; CryptoManager implementation will be used (falling back to the default one if ; none is found). ;CryptoManager=default ; ; AccessControlManager selects the type of AC framework. Possible values: ; "default" - no AC ; "smack-ac" - Smack AC ; "mssf-ac" - MSSF AC ; "apparmor-ac" - AppArmor AC ; (https://launchpad.net/signon-apparmor-extension) ; If omitted, the first extension plugin found to provide a suitable ; AccessControlManager implementation will be used (falling back to the default ; one if none is found). ;AccessControlManager=default ; ; SecretsStorage selects the storage backend for secrets. Possible values: ; "default" - unencrypted SQLite DB ; "gnome-keyring" - backend using libsecret's API ; (https://launchpad.net/signon-keyring-extension) ; If omitted, the first extension plugin found to provide a suitable ; SecretsStorage implementation will be used (falling back to the default ; one if none is found). ;SecretsStorage=default ; FileSystemName=signonfs Size=8 FileSystemType=ext2 [ObjectTimeouts] ; All the values are in seconds IdentityTimeout=30 AuthSessionTimeout=30 ; Set the timeout to 0 to disable quitting due to inactivity DaemonTimeout=5 signond-nicolasfella/src/signond/signondaemon.cpp0000664000175000017500000005366214615454535022510 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ extern "C" { #include #include #include } #include #include #include #include #include #include #include #include #include #include "SignOn/misc.h" #include "backup.h" #include "signondaemon.h" #include "signond-common.h" #include "signontrace.h" #include "signondaemonadaptor.h" #include "signonidentity.h" #include "signonauthsession.h" #include "accesscontrolmanagerhelper.h" #define SIGNON_RETURN_IF_CAM_UNAVAILABLE(_ret_arg_) do { \ if (m_pCAMManager && !m_pCAMManager->credentialsSystemOpened()) { \ setLastError(internalServerErrName, \ internalServerErrStr + \ QLatin1String("Could not access Signon " \ "Database.")); \ return _ret_arg_; \ } \ } while(0) using namespace SignOn; namespace SignonDaemonNS { /* ---------------------- SignonDaemonConfiguration ---------------------- */ SignonDaemonConfiguration::SignonDaemonConfiguration(): m_pluginsDir(QLatin1String(SIGNOND_PLUGINS_DIR)), m_extensionsDir(QLatin1String(SIGNOND_EXTENSIONS_DIR)), m_camConfiguration(), m_daemonTimeout(0), // 0 = no timeout m_identityTimeout(300),//secs m_authSessionTimeout(300)//secs {} SignonDaemonConfiguration::~SignonDaemonConfiguration() { TRACE(); } /* --- Configuration file template --- [General] UseSecureStorage=yes StoragePath=~/.signon/ ;0 - fatal, 1 - critical(default), 2 - info/debug LoggingLevel=1 [SecureStorage] FileSystemName=signonfs Size=8 FileSystemType=ext2 [ObjectTimeouts] IdentityTimeout=300 AuthSessionTimeout=300 */ void SignonDaemonConfiguration::load() { QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); //Daemon configuration file QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, environment.value(QLatin1String("SSO_CONFIG_FILE_DIR"), QLatin1String("/etc"))); QSettings settings(QLatin1String("signond")); int loggingLevel = settings.value(QLatin1String("LoggingLevel"), 1).toInt(); setLoggingLevel(loggingLevel); QString cfgStoragePath = settings.value(QLatin1String("StoragePath")).toString(); if (!cfgStoragePath.isEmpty()) { QString storagePath = QDir(cfgStoragePath).path(); m_camConfiguration.setStoragePath(storagePath); } else { QString xdgConfigHome = QString::fromLocal8Bit(qgetenv("XDG_CONFIG_HOME")); if (xdgConfigHome.isEmpty()) xdgConfigHome = QDir::homePath() + QLatin1String("/.config"); m_camConfiguration.setStoragePath(xdgConfigHome + QLatin1String("/signond")); } // Secure storage // Support legacy setting "UseSecureStorage" QString useSecureStorage = settings.value(QLatin1String("UseSecureStorage")).toString(); if (useSecureStorage == QLatin1String("yes") || useSecureStorage == QLatin1String("true")) { m_camConfiguration.addSetting(QLatin1String("CryptoManager"), QLatin1String("cryptsetup")); } settings.beginGroup(QLatin1String("SecureStorage")); QVariantMap storageOptions; foreach (const QString &key, settings.childKeys()) { m_camConfiguration.addSetting(key, settings.value(key)); } settings.endGroup(); //Timeouts settings.beginGroup(QLatin1String("ObjectTimeouts")); bool isOk = false; uint aux = settings.value(QLatin1String("IdentityTimeout")).toUInt(&isOk); if (isOk) m_identityTimeout = aux; aux = settings.value(QLatin1String("AuthSessionTimeout")).toUInt(&isOk); if (isOk) m_authSessionTimeout = aux; aux = settings.value(QLatin1String("DaemonTimeout")).toUInt(&isOk); if (isOk) m_daemonTimeout = aux; settings.endGroup(); //Environment variables int value = 0; if (environment.contains(QLatin1String("SSO_DAEMON_TIMEOUT"))) { value = environment.value( QLatin1String("SSO_DAEMON_TIMEOUT")).toInt(&isOk); if (value > 0 && isOk) m_daemonTimeout = value; } if (environment.contains(QLatin1String("SSO_IDENTITY_TIMEOUT"))) { value = environment.value( QLatin1String("SSO_IDENTITY_TIMEOUT")).toInt(&isOk); if (value > 0 && isOk) m_identityTimeout = value; } if (environment.contains(QLatin1String("SSO_AUTHSESSION_TIMEOUT"))) { value = environment.value( QLatin1String("SSO_AUTHSESSION_TIMEOUT")).toInt(&isOk); if (value > 0 && isOk) m_authSessionTimeout = value; } if (environment.contains(QLatin1String("SSO_LOGGING_LEVEL"))) { value = environment.value( QLatin1String("SSO_LOGGING_LEVEL")).toInt(&isOk); if (isOk) setLoggingLevel(value); } QString logOutput = environment.value(QLatin1String("SSO_LOGGING_OUTPUT"), QLatin1String("syslog")); SignonTrace::initialize(logOutput == QLatin1String("syslog") ? SignonTrace::Syslog : SignonTrace::Stdout); if (environment.contains(QLatin1String("SSO_STORAGE_PATH"))) { m_camConfiguration.setStoragePath( environment.value(QLatin1String("SSO_STORAGE_PATH"))); } if (environment.contains(QLatin1String("SSO_PLUGINS_DIR"))) { m_pluginsDir = environment.value(QLatin1String("SSO_PLUGINS_DIR")); } if (environment.contains(QLatin1String("SSO_EXTENSIONS_DIR"))) { m_extensionsDir = environment.value(QLatin1String("SSO_EXTENSIONS_DIR")); } QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); if (!runtimeDir.isEmpty()) { QString socketFileName = QString::fromLatin1("%1/" SIGNOND_SOCKET_FILENAME).arg(runtimeDir); QDir socketDir = QFileInfo(socketFileName).absoluteDir(); if (!socketDir.exists() && !socketDir.mkpath(socketDir.path())) { BLAME() << "Cannot create socket directory" << socketDir; } else { m_busAddress = QString::fromLatin1("unix:path=%1").arg(socketFileName); } } else { BLAME() << "XDG_RUNTIME_DIR unset, disabling p2p bus"; } } /* ---------------------- SignonDaemon ---------------------- */ const QString internalServerErrName = SIGNOND_INTERNAL_SERVER_ERR_NAME; const QString internalServerErrStr = SIGNOND_INTERNAL_SERVER_ERR_STR; static int sigFd[2]; SignonDaemon *SignonDaemon::m_instance = NULL; SignonDaemon::SignonDaemon(QObject *parent): QObject(parent), m_configuration(0), m_pCAMManager(0), m_dbusServer(0) { // Files created by signond must be unreadable by "other" umask(S_IROTH | S_IWOTH); // Register D-Bus meta types qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); } SignonDaemon::~SignonDaemon() { ::close(sigFd[0]); ::close(sigFd[1]); delete m_dbusServer; SignonAuthSession::stopAllAuthSessions(); m_storedIdentities.clear(); if (m_pCAMManager) { m_pCAMManager->closeCredentialsSystem(); delete m_pCAMManager; } QDBusConnection sessionConnection = QDBusConnection::sessionBus(); sessionConnection.unregisterObject(SIGNOND_DAEMON_OBJECTPATH); sessionConnection.unregisterService(SIGNOND_SERVICE); delete m_configuration; QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); } void SignonDaemon::setupSignalHandlers() { if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigFd) != 0) BLAME() << "Couldn't create HUP socketpair"; m_sigSn = new QSocketNotifier(sigFd[1], QSocketNotifier::Read, this); connect(m_sigSn, SIGNAL(activated(int)), this, SLOT(handleUnixSignal())); } void SignonDaemon::signalHandler(int signal) { int ret = ::write(sigFd[0], &signal, sizeof(signal)); Q_UNUSED(ret); } void SignonDaemon::handleUnixSignal() { m_sigSn->setEnabled(false); int signal; int ret = read(sigFd[1], &signal, sizeof(signal)); Q_UNUSED(ret); TRACE() << "signal received: " << signal; switch (signal) { case SIGHUP: { TRACE() << "\n\n SIGHUP \n\n"; //todo restart daemon deleteLater(); // reset the m_instance m_instance = NULL; QMetaObject::invokeMethod(instance(), "init", Qt::QueuedConnection); break; } case SIGTERM: { TRACE() << "\n\n SIGTERM \n\n"; //gently stop daemon deleteLater(); QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); break; } case SIGINT: { TRACE() << "\n\n SIGINT \n\n"; //gently stop daemon deleteLater(); QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); break; } default: break; } m_sigSn->setEnabled(true); } SignonDaemon *SignonDaemon::instance() { if (m_instance != NULL) return m_instance; QCoreApplication *app = QCoreApplication::instance(); if (!app) qFatal("SignonDaemon requires a QCoreApplication instance to be " "constructed first"); TRACE() << "Creating new daemon instance."; m_instance = new SignonDaemon(app); return m_instance; } void SignonDaemon::init() { if (!(m_configuration = new SignonDaemonConfiguration)) qWarning("SignonDaemon could not create the configuration object."); m_configuration->load(); QCoreApplication *app = QCoreApplication::instance(); if (!app) qFatal("SignonDaemon requires a QCoreApplication instance to be " "constructed first"); setupSignalHandlers(); m_pCAMManager = new CredentialsAccessManager(m_configuration->camConfiguration()); #ifdef ENABLE_BACKUP /* backup dbus interface */ bool backupMode = app->arguments().contains(QLatin1String("-backup")); (void)new Backup(m_pCAMManager, backupMode, this); if (backupMode) { TRACE() << "Signond initialized in backup mode."; //skip rest of initialization in backup mode return; } #endif /* DBus Service init */ QDBusConnection connection = SIGNOND_BUS; if (!connection.isConnected()) { QDBusError err = connection.lastError(); TRACE() << "Connection cannot be established:" << err.errorString(err.type()); TRACE() << err.message(); qFatal("SignonDaemon requires DBus to start working"); } QDBusConnection::RegisterOptions registerOptions = QDBusConnection::ExportAllContents; (void)new SignonDaemonAdaptor(this); registerOptions = QDBusConnection::ExportAdaptors; // p2p connection #ifdef ENABLE_P2P m_dbusServer = new QDBusServer(m_configuration->busAddress(), this); QObject::connect(m_dbusServer, SIGNAL(newConnection(const QDBusConnection &)), this, SLOT(onNewConnection(const QDBusConnection &))); #endif // session bus if (!connection.registerObject(SIGNOND_DAEMON_OBJECTPATH, this, registerOptions)) { TRACE() << "Object cannot be registered"; qFatal("SignonDaemon requires to register daemon's object"); } if (!connection.registerService(SIGNOND_SERVICE)) { QDBusError err = connection.lastError(); TRACE() << "Service cannot be registered: " << err.errorString(err.type()); qFatal("SignonDaemon requires to register daemon's service"); } // handle D-Bus disconnection connection.connect(QString(), QLatin1String("/org/freedesktop/DBus/Local"), QLatin1String("org.freedesktop.DBus.Local"), QLatin1String("Disconnected"), this, SLOT(onDisconnected())); initExtensions(); if (!initStorage()) BLAME() << "Signond: Cannot initialize credentials storage."; if (m_configuration->daemonTimeout() > 0) { SignonDisposable::invokeOnIdle(m_configuration->daemonTimeout(), this, SLOT(deleteLater())); } TRACE() << "Signond SUCCESSFULLY initialized."; } void SignonDaemon::onNewConnection(const QDBusConnection &connection) { TRACE() << "New p2p connection" << connection.name(); QDBusConnection conn(connection); if (!conn.registerObject(SIGNOND_DAEMON_OBJECTPATH, this, QDBusConnection::ExportAdaptors)) { qFatal("Failed to register SignonDaemon object"); } } void SignonDaemon::initExtensions() { /* Scan the directory containing signond extensions and attempt loading * all of them. */ QDir dir(m_configuration->extensionsDir()); QStringList filters(QLatin1String("lib*.so")); QStringList extensionList = dir.entryList(filters, QDir::Files); foreach(const QString &filename, extensionList) initExtension(dir.filePath(filename)); } void SignonDaemon::initExtension(const QString &filePath) { TRACE() << "Loading plugin " << filePath; QPluginLoader pluginLoader(filePath); QObject *plugin = pluginLoader.instance(); if (!plugin) { qWarning() << "Couldn't load plugin:" << pluginLoader.errorString(); return; } /* Check whether the extension implements some useful objects; if not, * unload it. */ if (!m_pCAMManager->initExtension(plugin)) pluginLoader.unload(); } bool SignonDaemon::initStorage() { if (!m_pCAMManager->credentialsSystemOpened()) { m_pCAMManager->finalize(); if (!m_pCAMManager->init()) { BLAME() << "CAM initialization failed"; return false; } // If encryption is in use this will just open the metadata DB if (!m_pCAMManager->openCredentialsSystem()) { qCritical("Signond: Cannot open CAM credentials system..."); return false; } } else { TRACE() << "Secure storage already initialized..."; return false; } return true; } void SignonDaemon::onIdentityStored(SignonIdentity *identity) { m_storedIdentities.insert(identity->id(), identity); } void SignonDaemon::onIdentityDestroyed() { SignonIdentity *identity = qobject_cast(sender()); m_storedIdentities.remove(identity->id()); } void SignonDaemon::watchIdentity(SignonIdentity *identity) { QObject::connect(identity, SIGNAL(stored(SignonIdentity*)), this, SLOT(onIdentityStored(SignonIdentity*))); QObject::connect(identity, SIGNAL(unregistered()), this, SLOT(onIdentityDestroyed())); if (identity->id() != SIGNOND_NEW_IDENTITY) { m_storedIdentities.insert(identity->id(), identity); } } SignonIdentity *SignonDaemon::registerNewIdentity() { clearLastError(); TRACE() << "Registering new identity:"; SignonIdentity *identity = SignonIdentity::createIdentity(SIGNOND_NEW_IDENTITY, this); Q_ASSERT(identity != NULL); watchIdentity(identity); return identity; } int SignonDaemon::identityTimeout() const { return (m_configuration == NULL ? 300 : m_configuration->identityTimeout()); } int SignonDaemon::authSessionTimeout() const { return (m_configuration == NULL ? 300 : m_configuration->authSessionTimeout()); } SignonIdentity *SignonDaemon::getIdentity(const quint32 id, QVariantMap &identityData) { clearLastError(); SIGNON_RETURN_IF_CAM_UNAVAILABLE(0); TRACE() << "Registering identity:" << id; //1st check if the existing identity is in cache SignonIdentity *identity = m_storedIdentities.value(id, NULL); //if not create it if (identity == NULL) identity = SignonIdentity::createIdentity(id, this); Q_ASSERT(identity != NULL); bool ok; SignonIdentityInfo info = identity->queryInfo(ok, false); if (info.isNew()) { setLastError(SIGNOND_IDENTITY_NOT_FOUND_ERR_NAME, SIGNOND_IDENTITY_NOT_FOUND_ERR_STR); identity->destroy(); return 0; } watchIdentity(identity); identity->keepInUse(); identityData = info.toMap(); TRACE() << "DONE REGISTERING IDENTITY"; return identity; } QStringList SignonDaemon::queryMethods() { QDir pluginsDir(m_configuration->pluginsDir()); //TODO: in the future remove the sym links comment QStringList fileNames = pluginsDir.entryList( QStringList() << QLatin1String("*.so*"), QDir::Files | QDir::NoDotAndDotDot); QStringList ret; QString fileName; foreach (fileName, fileNames) { if (fileName.startsWith(QLatin1String("lib"))) { fileName = fileName.mid(3, fileName.indexOf(QLatin1String("plugin")) -3); if ((fileName.length() > 0) && !ret.contains(fileName)) ret << fileName; } } return ret; } QStringList SignonDaemon::queryMechanisms(const QString &method) { clearLastError(); TRACE() << method; PluginProxy *plugin = PluginProxy::createNewPluginProxy(method); if (!plugin) { TRACE() << "Could not load plugin of type: " << method; setLastError(SIGNOND_METHOD_NOT_KNOWN_ERR_NAME, SIGNOND_METHOD_NOT_KNOWN_ERR_STR + QString::fromLatin1("Method %1 is not known or could " "not load specific configuration."). arg(method)); return QStringList(); } QStringList mechs = plugin->mechanisms(); delete plugin; return mechs; } QList SignonDaemon::queryIdentities(const QVariantMap &filter) { clearLastError(); SIGNON_RETURN_IF_CAM_UNAVAILABLE(QList()); TRACE() << "Querying identities"; CredentialsDB *db = m_pCAMManager->credentialsDB(); if (!db) { qCritical() << Q_FUNC_INFO << m_pCAMManager->lastError(); return QList(); } QMap filterLocal; QMapIterator it(filter); while (it.hasNext()) { it.next(); filterLocal.insert(it.key(), it.value().toString()); } QList credentials = db->credentials(filterLocal); if (db->errorOccurred()) { setLastError(internalServerErrName, internalServerErrStr + QLatin1String("Querying database error occurred.")); return QList(); } QList mapList; foreach (const SignonIdentityInfo &info, credentials) { mapList.append(info.toMap()); } return mapList; } bool SignonDaemon::clear() { clearLastError(); SIGNON_RETURN_IF_CAM_UNAVAILABLE(false); TRACE() << "\n\n\n Clearing DB\n\n"; CredentialsDB *db = m_pCAMManager->credentialsDB(); if (!db) { qCritical() << Q_FUNC_INFO << m_pCAMManager->lastError(); return false; } if (!db->clear()) { setLastError(SIGNOND_INTERNAL_SERVER_ERR_NAME, SIGNOND_INTERNAL_SERVER_ERR_STR + QLatin1String("Database error occurred.")); return false; } return true; } SignonAuthSession *SignonDaemon::getAuthSession(const quint32 id, const QString type, pid_t ownerPid) { clearLastError(); SignonAuthSession *authSession = SignonAuthSession::createAuthSession(id, type, this, ownerPid); if (authSession == NULL) { setLastError(SIGNOND_METHOD_NOT_KNOWN_ERR_NAME, SIGNOND_METHOD_NOT_KNOWN_ERR_STR); return 0; } return authSession; } void SignonDaemon::onDisconnected() { TRACE() << "Disconnected from session bus: exiting"; this->deleteLater(); QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); } void SignonDaemon::setLastError(const QString &name, const QString &msg) { m_lastErrorName = name; m_lastErrorMessage = msg; } void SignonDaemon::clearLastError() { m_lastErrorName = QString(); m_lastErrorMessage = QString(); } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signondaemon.h0000664000175000017500000001163414615454535022146 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONDAEMON_H_ #define SIGNONDAEMON_H_ extern "C" { #include #include #include #include #include } #include #include #include "credentialsaccessmanager.h" #ifndef SIGNOND_PLUGINS_DIR #define SIGNOND_PLUGINS_DIR "/usr/lib/signon" #endif #ifndef SIGNOND_PLUGIN_PREFIX #define SIGNOND_PLUGIN_PREFIX QLatin1String("lib") #endif #ifndef SIGNOND_PLUGIN_SUFFIX #define SIGNOND_PLUGIN_SUFFIX QLatin1String("plugin.so") #endif class QSocketNotifier; namespace SignonDaemonNS { /*! * @class SignonDaemonConfiguration * The daemon's configuration object; * loads date from the daemon configuration file. */ class SignonDaemonConfiguration { public: SignonDaemonConfiguration(); ~SignonDaemonConfiguration(); const CAMConfiguration &camConfiguration() const { return m_camConfiguration; } void setEncryptionPassphrase(const QByteArray &passphrase) { m_camConfiguration.m_encryptionPassphrase = passphrase; } void load(); QString pluginsDir() const { return m_pluginsDir; } QString extensionsDir() const { return m_extensionsDir; } QString busAddress() const { return m_busAddress; } uint daemonTimeout() const { return m_daemonTimeout; } uint identityTimeout() const { return m_identityTimeout; } uint authSessionTimeout() const { return m_authSessionTimeout; } private: QString m_pluginsDir; QString m_extensionsDir; QString m_busAddress; // storage configuration CAMConfiguration m_camConfiguration; //object timeouts uint m_daemonTimeout; uint m_identityTimeout; uint m_authSessionTimeout; }; class SignonIdentity; /*! * @class SignonDaemon * Daemon core. * @todo description. */ class SignonDaemon: public QObject, protected QDBusContext { Q_OBJECT friend class SignonSessionCore; friend class SignonDaemonAdaptor; public: static SignonDaemon *instance(); virtual ~SignonDaemon(); Q_INVOKABLE void init(); /*! * Returns the number of seconds of inactivity after which identity * objects might be automatically deleted. */ int identityTimeout() const; int authSessionTimeout() const; public: SignonIdentity *registerNewIdentity(); SignonIdentity *getIdentity(const quint32 id, QVariantMap &identityData); SignonAuthSession *getAuthSession(const quint32 id, const QString type, pid_t ownerPid); QStringList queryMethods(); QStringList queryMechanisms(const QString &method); QList queryIdentities(const QVariantMap &filter); bool clear(); QString lastErrorName() const { return m_lastErrorName; } QString lastErrorMessage() const { return m_lastErrorMessage; } bool lastErrorIsValid() const { return !m_lastErrorName.isEmpty(); } private Q_SLOTS: void onDisconnected(); void onNewConnection(const QDBusConnection &connection); void onIdentityStored(SignonIdentity *identity); void onIdentityDestroyed(); private: SignonDaemon(QObject *parent); void initExtensions(); void initExtension(const QString &filePath); bool initStorage(); void watchIdentity(SignonIdentity *identity); void setupSignalHandlers(); void setLastError(const QString &name, const QString &msg); void clearLastError(); private: /* * The list of created SignonIdentities * */ QMap m_storedIdentities; SignonDaemonConfiguration *m_configuration; /* * The instance of CAM * */ CredentialsAccessManager *m_pCAMManager; int m_identityTimeout; int m_authSessionTimeout; QDBusServer *m_dbusServer; QString m_lastErrorName; QString m_lastErrorMessage; /* * UNIX signals handling related * */ public: static void signalHandler(int signal); Q_INVOKABLE void handleUnixSignal(); private: QSocketNotifier *m_sigSn; static SignonDaemon *m_instance; }; //class SignonDaemon } //namespace SignonDaemonNS #endif /* SIGNONDAEMON_H_ */ signond-nicolasfella/src/signond/signondisposable.cpp0000664000175000017500000001005314615454535023355 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signondisposable.h" #include namespace SignonDaemonNS { static QList disposableObjects; static QPointer notifyTimer = 0; static QPointer disposeTimer = 0; SignonDisposable::SignonDisposable(int maxInactivity, QObject *parent): QObject(parent), maxInactivity(maxInactivity), autoDestruct(true) { disposableObjects.append(this); if (disposeTimer != 0) { int interval = (maxInactivity + 2) * 1000; if (interval > disposeTimer->interval()) disposeTimer->setInterval(interval); QObject::connect(disposeTimer, SIGNAL(timeout()), this, SLOT(destroyUnused())); } // mark as used keepInUse(); } SignonDisposable::~SignonDisposable() { disposableObjects.removeOne(this); } void SignonDisposable::keepInUse() const { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { qWarning("Couldn't get time from monotonic clock"); return; } lastActivity = ts.tv_sec; if (notifyTimer != 0) { notifyTimer->stop(); } if (disposeTimer != 0) { disposeTimer->start(); } } void SignonDisposable::setAutoDestruct(bool value) const { autoDestruct = value; keepInUse(); } void SignonDisposable::invokeOnIdle(int maxInactivity, QObject *object, const char *member) { notifyTimer = new QTimer(object); notifyTimer->setSingleShot(true); notifyTimer->setInterval(maxInactivity * 1000); QObject::connect(notifyTimer, SIGNAL(timeout()), object, member); /* In addition to the notifyTimer, we create another timer to let * destroyUnused() to run when we expect that some SignonDisposable object * might be inactive: that is, a couple of seconds later than the maximum * inactivity interval. This timer is triggered by the keepInUse() method. */ disposeTimer = new QTimer(object); disposeTimer->setSingleShot(true); int disposableMaxInactivity = 0; foreach (SignonDisposable *disposable, disposableObjects) { QObject::connect(disposeTimer, SIGNAL(timeout()), disposable, SLOT(destroyUnused())); if (disposableMaxInactivity < disposable->maxInactivity) disposableMaxInactivity = disposable->maxInactivity; } // Add a couple of seconds, to run the check after the objects are inactive disposeTimer->setInterval((disposableMaxInactivity + 2) * 1000); } void SignonDisposable::destroyUnused() { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { qWarning("Couldn't get time from monotonic clock"); return; } foreach (SignonDisposable *object, disposableObjects) { if (object->autoDestruct && (ts.tv_sec - object->lastActivity > object->maxInactivity)) { TRACE() << "Object unused, deleting: " << object; object->destroy(); disposableObjects.removeOne(object); } } if (disposableObjects.isEmpty() && notifyTimer != 0) { TRACE() << "No disposable objects, starting notification timer"; notifyTimer->start(); } } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signondisposable.h0000664000175000017500000000556014615454535023031 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONDISPOSABLE_H_ #define SIGNONDISPOSABLE_H_ #include "signond-common.h" #include #include namespace SignonDaemonNS { /*! * @class SignonDisposable * * Base class for server objects that can be automatically destroyed after * a certain period of inactivity. */ class SignonDisposable: public QObject { Q_OBJECT protected: virtual ~SignonDisposable(); public: /*! * Construct an object that can be automatically destroyed after * having being unused for @maxInactivity seconds. * * @param maxInactivity the number of seconds of inactivity. * @param parent the parent object. */ SignonDisposable(int maxInactivity, QObject *parent); /*! * Performs any predestruction operations and the destruction itself. * Reimplement this for smoother control. */ virtual void destroy() { deleteLater(); } /*! * Mark the object as used. Calling this method causes the inactivity * timer to be reset. */ void keepInUse() const; /*! * Mark the object as used. Calling this method enables/disables * autodestruction. * @param value enable/disable autodestruction */ void setAutoDestruct(bool value = true) const; /*! * Invoke the specified method on @object when there are no * disposable objects for more than @maxInactivity seconds. * * To keep the implementation simpler, this function can be called only * once, and the @member variable must still be accessible when the method * will be invoked (use a static string). */ static void invokeOnIdle(int maxInactivity, QObject *object, const char *member); public Q_SLOTS: /*! * Deletes all disposable object for which the inactivity time has * elapsed. */ static void destroyUnused(); private: int maxInactivity; mutable time_t lastActivity; mutable bool autoDestruct; }; //class SignonDaemon } //namespace SignonDaemonNS #endif /* SIGNONDISPOSABLE_H_ */ signond-nicolasfella/src/signond/signonidentity.h0000664000175000017500000000740414615454535022534 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONIDENTITY_H_ #define SIGNONIDENTITY_H_ #include #include "pluginproxy.h" #include "error.h" #include "signond-common.h" #include "signondaemon.h" #include "signondisposable.h" #include "signonidentityinfo.h" #include "credentialsaccessmanager.h" #include "signonui_interface.h" #include namespace SignonDaemonNS { class SignonIdentityAdaptor; /*! * @class SignonIdentity * Daemon side representation of identity. * @todo description. */ class SignonIdentity: public SignonDisposable { Q_OBJECT friend class SignonIdentityAdaptor; virtual ~SignonIdentity(); public: typedef SignonIdentityAdaptor Adaptor; void destroy(); static SignonIdentity *createIdentity(quint32 id, SignonDaemon *parent); quint32 id() const { return m_id; } SignonIdentityInfo queryInfo(bool &ok, bool queryPassword = true); quint32 storeCredentials(const SignonIdentityInfo &info); typedef std::function VerifyUserCb; typedef std::function CredentialsUpdateCb; typedef std::function RemoveCb; typedef std::function SignOutCb; public Q_SLOTS: void requestCredentialsUpdate(const QString &message, const CredentialsUpdateCb &callback); Error getInfo(SignonIdentityInfo *info); Error addReference(const QString &reference, const QString &appId); Error removeReference(const QString &reference, const QString &appId); void verifyUser(const QVariantMap ¶ms, const VerifyUserCb &callback); Error verifySecret(const QString &secret, bool *verified); void remove(const RemoveCb &callback); void signOut(const SignOutCb &callback); Error store(const QVariantMap &info, const QString &appId, quint32 *id); void queryUiSlot(QDBusPendingCallWatcher *call, const CredentialsUpdateCb &callback); void verifyUiSlot(QDBusPendingCallWatcher *call, const VerifyUserCb &callback); Q_SIGNALS: void unregistered(); //TODO - split this into the 3 separate signals(updated, removed, signed out) void infoUpdated(int); void stored(SignonIdentity *identity); private Q_SLOTS: void removeCompleted(QDBusPendingCallWatcher *call, const RemoveCb &callback); void signOutCompleted(QDBusPendingCallWatcher *call, const SignOutCb &callback); void onCredentialsUpdated(quint32 id); private: SignonIdentity(quint32 id, int timeout, SignonDaemon *parent); void queryUserPassword(const QVariantMap ¶ms, const VerifyUserCb &callback); private: quint32 m_id; SignonUiAdaptor *m_signonui; SignonIdentityInfo *m_pInfo; bool m_destroyed; }; //class SignonDaemon } //namespace SignonDaemonNS #endif /* SIGNONIDENTITY_H_ */ signond-nicolasfella/src/signond/signonidentityadaptor.cpp0000664000175000017500000002461714615454535024447 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signonidentityadaptor.h" #include "erroradaptor.h" #include "signonidentity.h" #include "accesscontrolmanagerhelper.h" namespace SignonDaemonNS { SignonIdentityAdaptor::SignonIdentityAdaptor(SignonIdentity *parent): QObject(parent), m_parent(parent) { QObject::connect(parent, &SignonIdentity::infoUpdated, this, &SignonIdentityAdaptor::infoUpdated); QObject::connect(parent, &SignonIdentity::unregistered, this, [this]() { Q_EMIT unregistered(); // Destroying the adaptor also triggers unregisterObject() delete this; }); } SignonIdentityAdaptor::~SignonIdentityAdaptor() { } void SignonIdentityAdaptor::securityErrorReply(const char *failedMethodName) { QString errMsg; QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR << "Method:" << failedMethodName; errorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME, errMsg); TRACE() << "Method FAILED Access Control check:" << failedMethodName; } void SignonIdentityAdaptor::errorReply(const QString &name, const QString &message) { QDBusMessage msg = this->message(); msg.setDelayedReply(true); QDBusMessage errReply = msg.createErrorReply(name, message); connection().send(errReply); } quint32 SignonIdentityAdaptor::requestCredentialsUpdate(const QString &msg) { const QDBusContext &context = *this; QDBusConnection connection = context.connection(); const QDBusMessage &message = context.message(); /* Access Control */ if (!AccessControlManagerHelper::instance()->isPeerAllowedToUseIdentity( PeerContext(connection, message), m_parent->id())) { securityErrorReply(__func__); return 0; } auto callback = [=](quint32 ret, const Error &error) { if (!error) { QDBusMessage dbusreply = message.createReply(); dbusreply << ret; connection.send(dbusreply); } else { connection.send(ErrorAdaptor(error).createReply(message)); } }; m_parent->requestCredentialsUpdate(msg, callback); setDelayedReply(true); return 0; // ignored } QVariantMap SignonIdentityAdaptor::getInfo() { const QDBusContext &context = *this; QDBusConnection connection = context.connection(); const QDBusMessage &message = context.message(); /* Access Control */ if (!AccessControlManagerHelper::instance()->isPeerAllowedToUseIdentity( PeerContext(connection, message), m_parent->id())) { securityErrorReply(__func__); return QVariantMap(); } SignonIdentityInfo info; Error error = m_parent->getInfo(&info); if (error) { connection.send(ErrorAdaptor(error).createReply(message)); } return info.toMap(); } void SignonIdentityAdaptor::addReference(const QString &reference) { const QDBusConnection &connection = this->connection(); const QDBusMessage &message = this->message(); /* Access Control */ if (!AccessControlManagerHelper::instance()->isPeerAllowedToUseIdentity( PeerContext(connection, message), m_parent->id())) { securityErrorReply(__func__); return; } QString appId = AccessControlManagerHelper::instance()->appIdOfPeer( PeerContext(connection, message)); Error error = m_parent->addReference(reference, appId); if (error) { connection.send(ErrorAdaptor(error).createReply(message)); } } void SignonIdentityAdaptor::removeReference(const QString &reference) { const QDBusConnection &connection = this->connection(); const QDBusMessage &message = this->message(); /* Access Control */ if (!AccessControlManagerHelper::instance()->isPeerAllowedToUseIdentity( PeerContext(connection, message), m_parent->id())) { securityErrorReply(__func__); return; } QString appId = AccessControlManagerHelper::instance()->appIdOfPeer( PeerContext(connection, message)); Error error = m_parent->removeReference(reference, appId); if (error) { connection.send(ErrorAdaptor(error).createReply(message)); } } bool SignonIdentityAdaptor::verifyUser(const QVariantMap ¶ms) { const QDBusContext &context = *this; QDBusConnection connection = context.connection(); const QDBusMessage &message = context.message(); /* Access Control */ if (!AccessControlManagerHelper::instance()->isPeerAllowedToUseIdentity( PeerContext(connection, message), m_parent->id())) { securityErrorReply(__func__); return false; } auto callback = [=](bool ret, const Error &error) { if (!error) { QDBusMessage dbusreply = message.createReply(); dbusreply << ret; connection.send(dbusreply); } else { connection.send(ErrorAdaptor(error).createReply(message)); } }; m_parent->verifyUser(params, callback); setDelayedReply(true); return false; // ignored } bool SignonIdentityAdaptor::verifySecret(const QString &secret) { const QDBusContext &context = *this; QDBusConnection connection = context.connection(); const QDBusMessage &message = context.message(); /* Access Control */ if (!AccessControlManagerHelper::instance()->isPeerAllowedToUseIdentity( PeerContext(connection, message), m_parent->id())) { securityErrorReply(__func__); return false; } bool verified = false; Error error = m_parent->verifySecret(secret, &verified); if (error) { connection.send(ErrorAdaptor(error).createReply(message)); } return verified; } void SignonIdentityAdaptor::remove() { const QDBusContext &context = *this; QDBusConnection connection = context.connection(); const QDBusMessage &message = context.message(); /* Access Control */ AccessControlManagerHelper::IdentityOwnership ownership = AccessControlManagerHelper::instance()->isPeerOwnerOfIdentity( PeerContext(connection, message), m_parent->id()); if (ownership != AccessControlManagerHelper::IdentityDoesNotHaveOwner) { //Identity has an owner if (ownership == AccessControlManagerHelper::ApplicationIsNotOwner && !AccessControlManagerHelper::instance()->isPeerKeychainWidget( PeerContext(connection, message))) { securityErrorReply(__func__); return; } } auto callback = [=](const Error &error) { if (!error) { connection.send(message.createReply()); } else { connection.send(ErrorAdaptor(error).createReply(message)); } }; m_parent->remove(callback); setDelayedReply(true); } bool SignonIdentityAdaptor::signOut() { const QDBusContext &context = *this; QDBusConnection connection = context.connection(); const QDBusMessage &message = context.message(); /* Access Control */ if (!AccessControlManagerHelper::instance()->isPeerAllowedToUseIdentity( PeerContext(connection, message), m_parent->id())) { securityErrorReply(__func__); return false; } auto callback = [=](bool signedOut, const Error &error) { if (!error) { QDBusMessage reply = message.createReply(); reply << signedOut; connection.send(reply); } else { connection.send(ErrorAdaptor(error).createReply(message)); } }; m_parent->signOut(callback); setDelayedReply(true); return false; // ignored } quint32 SignonIdentityAdaptor::store(const QVariantMap &info) { const QDBusContext &context = *this; QDBusConnection connection = context.connection(); const QDBusMessage &message = context.message(); quint32 id = info.value(QLatin1String("Id"), SIGNOND_NEW_IDENTITY).toInt(); /* Access Control */ if (id != SIGNOND_NEW_IDENTITY) { AccessControlManagerHelper::IdentityOwnership ownership = AccessControlManagerHelper::instance()->isPeerOwnerOfIdentity( PeerContext(connection, message), m_parent->id()); if (ownership != AccessControlManagerHelper::IdentityDoesNotHaveOwner) { //Identity has an owner if (ownership == AccessControlManagerHelper::ApplicationIsNotOwner && !AccessControlManagerHelper::instance()->isPeerKeychainWidget( PeerContext(connection, message))) { securityErrorReply(__func__); return 0; } } } QString appId = AccessControlManagerHelper::instance()->appIdOfPeer( PeerContext(connection, message)); Error error = m_parent->store(info, appId, &id); if (error) { connection.send(ErrorAdaptor(error).createReply(message)); } return id; } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signonidentityadaptor.h0000664000175000017500000000377214615454535024113 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONIDENTITYADAPTOR_H #define SIGNONIDENTITYADAPTOR_H #include #include #include "signond-common.h" #include "signonidentity.h" namespace SignonDaemonNS { class SignonIdentityAdaptor : public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "com.google.code.AccountsSSO.SingleSignOn.Identity") public: SignonIdentityAdaptor(SignonIdentity *parent); virtual ~SignonIdentityAdaptor(); public Q_SLOTS: quint32 requestCredentialsUpdate(const QString &message); QVariantMap getInfo(); void addReference(const QString &reference); void removeReference(const QString &reference); bool verifyUser(const QVariantMap ¶ms); bool verifySecret(const QString &secret); void remove(); bool signOut(); quint32 store(const QVariantMap &info); Q_SIGNALS: void unregistered(); void infoUpdated(int); private: void securityErrorReply(const char *failedMethodName); void errorReply(const QString &name, const QString &message); private: SignonIdentity *m_parent; }; } //namespace SignonDaemonNS #endif // SIGNONIDENTITYADAPTOR_H signond-nicolasfella/src/signond/signonidentityinfo.h0000664000175000017500000001336514615454535023413 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONIDENTITYINFO_H #define SIGNONIDENTITYINFO_H #include #include #include "signond/signoncommon.h" #include "signonsecuritycontext.h" namespace SignonDaemonNS { typedef QString MethodName; typedef QStringList MechanismsList; typedef QMap MethodMap; typedef QList SignonSecurityContextList; /*! * @struct SignonIdentityInfo * Daemon side representation of identity information. * @todo description. */ struct SignonIdentityInfo: protected QVariantMap { SignonIdentityInfo(); SignonIdentityInfo(const QVariantMap &info); const QVariantMap toMap() const; void update(const SignonIdentityInfo &info); void setNew() { setId(SIGNOND_NEW_IDENTITY); } bool isNew() const { return id() == SIGNOND_NEW_IDENTITY; } void setId(quint32 id) { insert(SIGNOND_IDENTITY_INFO_ID, id); } quint32 id() const { return value(SIGNOND_IDENTITY_INFO_ID, 0).toUInt(); } void setUserName(const QString &userName) { insert(SIGNOND_IDENTITY_INFO_USERNAME, userName); } QString userName() const { return value(SIGNOND_IDENTITY_INFO_USERNAME).toString(); } void setUserNameSecret(bool secret) { insert(SIGNOND_IDENTITY_INFO_USERNAME_IS_SECRET, secret); } bool isUserNameSecret() const { return value(SIGNOND_IDENTITY_INFO_USERNAME_IS_SECRET).toBool(); } void setPassword(const QString &password) { insert(SIGNOND_IDENTITY_INFO_SECRET, password); } QString password() const { return value(SIGNOND_IDENTITY_INFO_SECRET).toString(); } void removeSecrets() { remove(SIGNOND_IDENTITY_INFO_SECRET); if (isUserNameSecret()) remove(SIGNOND_IDENTITY_INFO_USERNAME); } bool hasSecrets() const { return contains(SIGNOND_IDENTITY_INFO_SECRET) || (isUserNameSecret() && contains(SIGNOND_IDENTITY_INFO_USERNAME)); } void setStorePassword(bool storePassword) { insert(SIGNOND_IDENTITY_INFO_STORESECRET, storePassword); } bool storePassword() const { return value(SIGNOND_IDENTITY_INFO_STORESECRET).toBool(); } void setCaption(const QString &caption) { insert(SIGNOND_IDENTITY_INFO_CAPTION, caption); } QString caption() const { return value(SIGNOND_IDENTITY_INFO_CAPTION).toString(); } void setRealms(const QStringList &realms) { insert(SIGNOND_IDENTITY_INFO_REALMS, realms); } QStringList realms() const { return value(SIGNOND_IDENTITY_INFO_REALMS).toStringList(); } void setMethods(const MethodMap &methods) { insert(SIGNOND_IDENTITY_INFO_AUTHMETHODS, QVariant::fromValue(methods)); } MethodMap methods() const { return value(SIGNOND_IDENTITY_INFO_AUTHMETHODS).value(); } void setAccessControlList(const SignonSecurityContextList &accessControlList) { insert(SIGNOND_IDENTITY_INFO_ACL, QVariant::fromValue(accessControlList)); } void setAccessControlList(const QStringList &accessControlList) { SignonSecurityContextList list; for (const QString &sysCtx: accessControlList) { SignonSecurityContext securityContext = SignonSecurityContext(sysCtx, QLatin1String("*")); list.append(securityContext); } insert(SIGNOND_IDENTITY_INFO_ACL, QVariant::fromValue(list)); } QStringList accessControlList() const { SignonSecurityContextList accessControlList = value(SIGNOND_IDENTITY_INFO_ACL).value(); QStringList list; for (const SignonSecurityContext &securityContext: accessControlList) { list.append(securityContext.systemContext()); } return list; } void setValidated(bool validated) { insert(SIGNOND_IDENTITY_INFO_VALIDATED, validated); } bool validated() const { return value(SIGNOND_IDENTITY_INFO_VALIDATED).toBool(); } void setType(quint32 type) { insert(SIGNOND_IDENTITY_INFO_TYPE, type); } quint32 type() const { return value(SIGNOND_IDENTITY_INFO_TYPE).toUInt(); } void setOwnerList(const QStringList &owners) { insert(SIGNOND_IDENTITY_INFO_OWNER, owners); } QStringList ownerList() const { return value(SIGNOND_IDENTITY_INFO_OWNER).toStringList(); } void setRefCount(int refCount) { insert(SIGNOND_IDENTITY_INFO_REFCOUNT, refCount); } int refCount() const { return value(SIGNOND_IDENTITY_INFO_REFCOUNT).toInt(); } bool checkMethodAndMechanism(const QString &method, const QString &mechanism, QString &allowedMechanism); }; //struct SignonIdentityInfo } //namespace SignonDaemonNS Q_DECLARE_METATYPE(SignonDaemonNS::MethodMap) Q_DECLARE_METATYPE(SignonDaemonNS::SignonSecurityContextList) #endif // SIGNONIDENTITYINFO_H signond-nicolasfella/src/signond/signonsecuritycontext.cpp0000664000175000017500000000451014615454535024505 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2018 elementary, Inc * * Contact: Corentin Noël * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signond-common.h" #include "signonsecuritycontext.h" #include #include #include namespace SignonDaemonNS { SignonSecurityContext::SignonSecurityContext() { } SignonSecurityContext::SignonSecurityContext(const QString &systemContext, const QString &applicationContext): m_systemContext(systemContext), m_applicationContext(applicationContext) { } QDBusArgument &operator<<(QDBusArgument &argument, const SignonSecurityContext &securityContext) { argument.beginStructure(); argument << securityContext.systemContext() << securityContext.applicationContext(); argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, SignonSecurityContext &securityContext) { QString systemContext; QString applicationContext; argument.beginStructure(); argument >> systemContext >> applicationContext; securityContext.setSystemContext(systemContext); securityContext.setApplicationContext(applicationContext); argument.endStructure(); return argument; } void SignonSecurityContext::setSystemContext(const QString &systemContext) { m_systemContext = systemContext; } QString SignonSecurityContext::systemContext() const { return m_systemContext; } void SignonSecurityContext::setApplicationContext(const QString &applicationContext) { m_applicationContext = applicationContext; } QString SignonSecurityContext::applicationContext() const { return m_applicationContext; } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signonsecuritycontext.h0000664000175000017500000000362714615454535024162 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2018 elementary, Inc * * Contact: Corentin Noël * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONSECURITYCONTEXT_H #define SIGNONSECURITYCONTEXT_H #include #include #include #include "signond/signoncommon.h" namespace SignonDaemonNS { /*! * @struct SignonSecurityContext * Daemon side representation of security context information. */ struct SignonSecurityContext { public: SignonSecurityContext(); SignonSecurityContext(const QString &systemContext, const QString &applicationContext); void setSystemContext(const QString &systemContext); QString systemContext() const; void setApplicationContext(const QString &applicationContext); QString applicationContext() const; private: QString m_systemContext; QString m_applicationContext; }; typedef QList SignonSecurityContextList; QDBusArgument &operator<<(QDBusArgument &argument, const SignonSecurityContext &securityContext); const QDBusArgument &operator>>(const QDBusArgument &argument, SignonSecurityContext &securityContext); } //namespace SignonDaemonNS Q_DECLARE_METATYPE(SignonDaemonNS::SignonSecurityContext) #endif // SIGNONSECURITYCONTEXT_H signond-nicolasfella/src/signond/signonsessioncore.h0000664000175000017500000001123014615454535023227 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONSESSIONCORE_H_ #define SIGNONSESSIONCORE_H_ #include #include /* * TODO: remove invocation of plugin operations into the main signond process */ #include "pluginproxy.h" #include "signondisposable.h" #include "signonsessioncoretools.h" #include using namespace SignOn; class SignonUiAdaptor; namespace SignonDaemonNS { class Error; class PeerContext; class SignonDaemon; /*! * @class SignonSessionCore * Daemon side representation of authentication session. * @todo description. */ class SignonSessionCore: public SignonDisposable { Q_OBJECT public: static SignonSessionCore *sessionCore(const quint32 id, const QString &method, SignonDaemon *parent); virtual ~SignonSessionCore(); quint32 id() const; QString method() const; bool setupPlugin(); /* * just for any case * */ static void stopAllAuthSessions(); void destroy(); typedef std::function ProcessCb; public Q_SLOTS: QStringList queryAvailableMechanisms(const QStringList &wantedMechanisms); void process(const PeerContext &peerContext, const QVariantMap &sessionDataVa, const QString &mechanism, const QString &cancelKey, const ProcessCb &callback); void cancel(const QString &cancelKey); void setId(quint32 id); /* When the credentials system is ready, session processing will begin. * This mechanism helps avoiding the display of eroneous secure storage * related messages on query credentials dialogs (e.g. The `No key present` * scenario - keys might actually be present but the querying of them is * not complete at the time of the auth. session processing). */ void credentialsSystemReady(); Q_SIGNALS: void stateChanged(const QString &requestId, int state, const QString &message); private Q_SLOTS: void startNewRequest(); void processResultReply(const QVariantMap &data); void processStore(const QVariantMap &data); void processUiRequest(const QVariantMap &data); void processRefreshRequest(const QVariantMap &data); void processError(int err, const QString &message); void stateChangedSlot(int state, const QString &message); void queryUiSlot(QDBusPendingCallWatcher *call); protected: SignonSessionCore(quint32 id, const QString &method, int timeout, QObject *parent); void childEvent(QChildEvent *ce); void customEvent(QEvent *event); private: void startProcess(); void replyError(const RequestData &request, int err, const QString &message); void processStoreOperation(const StoreOperation &operation); void requestDone(); private: PluginProxy *m_plugin; QQueue m_listOfRequests; SignonUiAdaptor *m_signonui; QDBusPendingCallWatcher *m_watcher; bool m_requestIsActive; bool m_canceled; uint m_id; QString m_method; /* the original request parameters, for the request currently being * processed */ QVariantMap m_clientData; //Temporary caching QString m_tmpUsername; QString m_tmpPassword; /* Flag used for handling post ui querying results' processing. * Secure storage not available events won't be posted if the current * session processing was not preceded by a signon UI query credentials * interaction, when this flag is set to true. */ bool m_queryCredsUiDisplayed; Q_DISABLE_COPY(SignonSessionCore) }; //class SignonDaemon } //namespace SignonDaemonNS #endif //SIGNONSESSIONQUEUE_H_ signond-nicolasfella/src/signond/signonsessioncoretools.h0000664000175000017500000000504214615454535024314 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONSESSIONCORETOOLS_H #define SIGNONSESSIONCORETOOLS_H #include #include #include "peercontext.h" #include "signonidentityinfo.h" #include namespace SignonDaemonNS { class Error; /*! * @brief Helper method which unites two variant maps. * @param map1 base map to be united with * @param map2 map to be united with base. If map2 and map1 contain common * keys, the values in map1 will be overwritten by map2 values * @returns a union of the map1 and map2 with unique keys, */ QVariantMap mergeVariantMaps(const QVariantMap &map1, const QVariantMap &map2); /*! * @class StoreOperation * Describes a credentials store operatation. */ struct StoreOperation { enum StoreType { Credentials = 0, Blob }; StoreOperation(const StoreType type); StoreOperation(const StoreOperation &src); ~StoreOperation(); public: StoreType m_storeType; SignonIdentityInfo m_info; //Blob store related QString m_authMethod; QVariantMap m_blobData; }; /*! * @class RequestData * Request data. * @todo description. */ struct RequestData { typedef std::function ProcessCb; RequestData(const PeerContext &peerContext, const QVariantMap ¶ms, const QString &mechanism, const QString &cancelKey, const ProcessCb &callback); RequestData(const RequestData &other); ~RequestData(); public: PeerContext m_peerContext; ProcessCb m_callback; QVariantMap m_params; QString m_mechanism; QString m_cancelKey; }; } //SignonDaemonNS #endif //SIGNONSESSIONCORETOOLS_H signond-nicolasfella/src/signond/signontrace.h0000664000175000017500000000510014615454535021770 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONTRACE_H #define SIGNONTRACE_H #include #include #include #include #include #include "signond-common.h" namespace SignOn { class SignonTrace { public: enum LogOutput { Syslog = 0, Stdout, }; ~SignonTrace() { m_pInstance = NULL; if (m_logOutput == Syslog) { closelog(); } } static void initialize(LogOutput logOutput) { if (m_pInstance) return; m_pInstance = new SignonTrace(logOutput); } static void output(QtMsgType type, const QMessageLogContext &context, const QString &msg) { Q_UNUSED(context); if (!m_pInstance) return; if (!criticalsEnabled()) { if (type <= QtCriticalMsg) return; } else if (!debugEnabled()) { if (type <= QtDebugMsg) return; } int priority; switch (type) { case QtWarningMsg: priority = LOG_WARNING; break; case QtCriticalMsg: priority = LOG_CRIT; break; case QtFatalMsg: priority = LOG_EMERG; break; case QtDebugMsg: /* fall through */ default: priority = LOG_INFO; break; } syslog(priority, "%s", msg.toUtf8().constData()); } private: SignonTrace(LogOutput logOutput): m_logOutput(logOutput) { if (logOutput == Syslog) { openlog(NULL, LOG_PID, LOG_DAEMON); qInstallMessageHandler(output); } } static SignonTrace *m_pInstance; LogOutput m_logOutput; }; SignonTrace *SignonTrace::m_pInstance = 0; } //namespace SignOn #endif // SIGNONTRACE_H signond-nicolasfella/src/signond/signonui_interface.cpp0000664000175000017500000000621414615454535023671 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signonui_interface.h" #include "signond-common.h" #include "SignOn/uisessiondata_priv.h" /* * Implementation of interface class SignonUiAdaptor */ SignonUiAdaptor::SignonUiAdaptor(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent): QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) { } SignonUiAdaptor::~SignonUiAdaptor() { } /* * Open a new dialog * */ QDBusPendingCall SignonUiAdaptor::queryDialog(const QVariantMap ¶meters) { QList argumentList; argumentList << parameters; return callWithArgumentListAndBigTimeout(QLatin1String("queryDialog"), argumentList); } /* * update the existing dialog * */ QDBusPendingCall SignonUiAdaptor::refreshDialog(const QVariantMap ¶meters) { QList argumentList; argumentList << parameters; return callWithArgumentListAndBigTimeout(QLatin1String("refreshDialog"), argumentList); } /* * cancel dialog request * */ void SignonUiAdaptor::cancelUiRequest(const QString &requestId) { QList argumentList; argumentList << requestId; callWithArgumentList(QDBus::NoBlock, QLatin1String("cancelUiRequest"), argumentList); } /* * Remove any data associated with the given identity. * */ QDBusPendingCall SignonUiAdaptor::removeIdentityData(quint32 id) { QList argumentList; argumentList << id; return asyncCallWithArgumentList(QLatin1String("removeIdentityData"), argumentList); } QDBusPendingCall SignonUiAdaptor::callWithArgumentListAndBigTimeout(const QString &method, const QList &args) { QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), method); if (!args.isEmpty()) msg.setArguments(args); return connection().asyncCall(msg, SIGNOND_MAX_TIMEOUT); } signond-nicolasfella/src/signond/signonui_interface.h0000664000175000017500000000410514615454535023333 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONUI_INTERFACE_H_ #define SIGNONUI_INTERFACE_H_ #include #include #include #include #include #include #include #include #include /* * Proxy class for interface com.nokia.singlesignonui */ class SignonUiAdaptor: public QDBusAbstractInterface { Q_OBJECT friend class SignonSecureStorageUiAdaptor; public: static inline const char *staticInterfaceName() { return "com.nokia.singlesignonui"; } public: SignonUiAdaptor(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); ~SignonUiAdaptor(); public Q_SLOTS: // METHODS QDBusPendingCall queryDialog(const QVariantMap ¶meters); QDBusPendingCall refreshDialog(const QVariantMap ¶meters); void cancelUiRequest(const QString &requestId); QDBusPendingCall removeIdentityData(quint32 id); protected: QDBusPendingCall callWithArgumentListAndBigTimeout( const QString &method, const QList &args = QList()); }; #endif signond-nicolasfella/src/signond/pluginproxy.cpp0000664000175000017500000003622614615454547022427 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "pluginproxy.h" #include #include #include #include #include #include #include #include "signond-common.h" #include "SignOn/uisessiondata_priv.h" #include "SignOn/signonplugincommon.h" /* * TODO: remove the "SignOn/authpluginif.h" include below after the removal * of the deprecated error handling (needed here only for the deprecated * AuthPluginError::PLUGIN_ERROR_GENERAL). */ #include "SignOn/authpluginif.h" // signon-plugins-common #include "SignOn/blobiohandler.h" #include "SignOn/ipc.h" using namespace SignOn; #define REMOTEPLUGIN_BIN_PATH QLatin1String("signonpluginprocess") #define PLUGINPROCESS_START_TIMEOUT 5000 #define PLUGINPROCESS_STOP_TIMEOUT 1000 using namespace SignOn; namespace SignonDaemonNS { /* ---------------------- PluginProcess ---------------------- */ PluginProcess::PluginProcess(QObject *parent): QProcess(parent) { } PluginProcess::~PluginProcess() { } /* ---------------------- PluginProxy ---------------------- */ PluginProxy::PluginProxy(QString type, QObject *parent): QObject(parent) { TRACE(); m_type = type; m_isProcessing = false; m_isResultObtained = false; m_currentResultOperation = -1; m_process = new PluginProcess(this); #ifdef SIGNOND_TRACE if (criticalsEnabled()) { const char *level = debugEnabled() ? "2" : "1"; QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(QLatin1String("SSO_DEBUG"), QLatin1String(level)); m_process->setProcessEnvironment(env); } #endif connect(m_process, SIGNAL(readyReadStandardError()), this, SLOT(onReadStandardError())); /* * TODO: some error handling should be added here, at least remove of * current request data from the top of the queue and reply an error code */ connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onExit(int, QProcess::ExitStatus))); connect(m_process, &PluginProcess::errorOccurred, this, &PluginProxy::onError); } PluginProxy::~PluginProxy() { if (m_process != NULL && m_process->state() != QProcess::NotRunning) { if (m_isProcessing) cancel(); stop(); /* Closing the write channel ensures that the plugin process * will not get stuck on the next read. */ m_process->closeWriteChannel(); if (!m_process->waitForFinished(PLUGINPROCESS_STOP_TIMEOUT)) { qCritical() << "The signon plugin does not react on demand to " "stop: need to kill it!!!"; m_process->kill(); if (!m_process->waitForFinished(PLUGINPROCESS_STOP_TIMEOUT)) { if (m_process->processId()) { qCritical() << "The signon plugin seems to ignore kill(), " "killing it from command line"; QString killProcessCommand(QString::fromLatin1("kill -9 %1").arg(m_process->processId())); QProcess::execute(killProcessCommand); } } } } } PluginProxy* PluginProxy::createNewPluginProxy(const QString &type) { PluginProxy *pp = new PluginProxy(type); QStringList args = QStringList() << pp->m_type; pp->m_process->start(REMOTEPLUGIN_BIN_PATH, args); QByteArray tmp; if (!pp->waitForStarted(PLUGINPROCESS_START_TIMEOUT)) { TRACE() << "The process cannot be started"; delete pp; return NULL; } if (!pp->readOnReady(tmp, PLUGINPROCESS_START_TIMEOUT)) { TRACE() << "The process cannot load plugin"; delete pp; return NULL; } if (debugEnabled()) { QString pluginType = pp->queryType(); if (pluginType != pp->m_type) { BLAME() << QString::fromLatin1("Plugin returned type '%1', " "expected '%2'"). arg(pluginType).arg(pp->m_type); } } pp->m_mechanisms = pp->queryMechanisms(); connect(pp->m_process, SIGNAL(readyRead()), pp, SLOT(onReadStandardOutput())); TRACE() << "The process is started"; return pp; } bool PluginProxy::process(const QVariantMap &inData, const QString &mechanism) { if (!restartIfRequired()) return false; m_isResultObtained = false; QVariant value = inData.value(SSOUI_KEY_UIPOLICY); m_uiPolicy = value.toInt(); QDataStream in(m_process); in << (quint32)PLUGIN_OP_PROCESS; in << mechanism; m_blobIOHandler->sendData(inData); m_isProcessing = true; return true; } bool PluginProxy::processUi(const QVariantMap &inData) { TRACE(); if (!restartIfRequired()) return false; QDataStream in(m_process); in << (quint32)PLUGIN_OP_PROCESS_UI; m_blobIOHandler->sendData(inData); m_isProcessing = true; return true; } bool PluginProxy::processRefresh(const QVariantMap &inData) { TRACE(); if (!restartIfRequired()) return false; QDataStream in(m_process); in << (quint32)PLUGIN_OP_REFRESH; m_blobIOHandler->sendData(inData); m_isProcessing = true; return true; } void PluginProxy::cancel() { TRACE(); QDataStream in(m_process); in << (quint32)PLUGIN_OP_CANCEL; } void PluginProxy::stop() { TRACE(); QDataStream in(m_process); in << (quint32)PLUGIN_OP_STOP; } bool PluginProxy::readOnReady(QByteArray &buffer, int timeout) { bool ready = m_process->waitForReadyRead(timeout); if (ready) { if (!m_process->bytesAvailable()) return false; while (m_process->bytesAvailable()) buffer += m_process->readAllStandardOutput(); } return ready; } bool PluginProxy::isProcessing() { return m_isProcessing; } void PluginProxy::blobIOError() { TRACE(); disconnect(m_blobIOHandler, SIGNAL(error()), this, SLOT(blobIOError())); stop(); connect(m_process, SIGNAL(readyRead()), this, SLOT(onReadStandardOutput())); emit processError( (int)Error::InternalServer, QLatin1String("Failed to I/O session data to/from the authentication " "plugin.")); } bool PluginProxy::isResultOperationCodeValid(const int opCode) const { if (opCode == PLUGIN_RESPONSE_RESULT || opCode == PLUGIN_RESPONSE_STORE || opCode == PLUGIN_RESPONSE_ERROR || opCode == PLUGIN_RESPONSE_SIGNAL || opCode == PLUGIN_RESPONSE_UI || opCode == PLUGIN_RESPONSE_REFRESHED) return true; return false; } void PluginProxy::onReadStandardOutput() { disconnect(m_process, SIGNAL(readyRead()), this, SLOT(onReadStandardOutput())); if (!m_process->bytesAvailable()) { qCritical() << "No information available on process"; m_isProcessing = false; emit processError(Error::InternalServer, QString()); return; } QDataStream reader(m_process); reader >> m_currentResultOperation; TRACE() << "PROXY RESULT OPERATION:" << m_currentResultOperation; if (!isResultOperationCodeValid(m_currentResultOperation)) { TRACE() << "Unknown operation code - skipping."; //flushing the stdin channel Q_UNUSED(m_process->readAllStandardOutput()); connect(m_process, SIGNAL(readyRead()), this, SLOT(onReadStandardOutput())); return; } if (m_currentResultOperation != PLUGIN_RESPONSE_SIGNAL && m_currentResultOperation != PLUGIN_RESPONSE_ERROR) { connect(m_blobIOHandler, SIGNAL(error()), this, SLOT(blobIOError())); int expectedDataSize = 0; reader >> expectedDataSize; TRACE() << "PROXY EXPECTED DATA SIZE:" << expectedDataSize; m_blobIOHandler->receiveData(expectedDataSize); } else { handlePluginResponse(m_currentResultOperation); } } void PluginProxy::sessionDataReceived(const QVariantMap &map) { handlePluginResponse(m_currentResultOperation, map); } void PluginProxy::handlePluginResponse(const quint32 resultOperation, const QVariantMap &sessionDataMap) { TRACE() << resultOperation; if (resultOperation == PLUGIN_RESPONSE_RESULT) { TRACE() << "PLUGIN_RESPONSE_RESULT"; m_isProcessing = false; if (!m_isResultObtained) emit processResultReply(sessionDataMap); else BLAME() << "Unexpected plugin response: "; m_isResultObtained = true; } else if (resultOperation == PLUGIN_RESPONSE_STORE) { TRACE() << "PLUGIN_RESPONSE_STORE"; if (!m_isResultObtained) emit processStore(sessionDataMap); else BLAME() << "Unexpected plugin store: "; } else if (resultOperation == PLUGIN_RESPONSE_UI) { TRACE() << "PLUGIN_RESPONSE_UI"; if (!m_isResultObtained) { bool allowed = true; if (m_uiPolicy == NoUserInteractionPolicy) allowed = false; if (m_uiPolicy == ValidationPolicy) { bool credentialsQueried = (sessionDataMap.contains(SSOUI_KEY_QUERYUSERNAME) || sessionDataMap.contains(SSOUI_KEY_QUERYPASSWORD)); bool captchaQueried = (sessionDataMap.contains(SSOUI_KEY_CAPTCHAIMG) || sessionDataMap.contains(SSOUI_KEY_CAPTCHAURL)); if (credentialsQueried && !captchaQueried) allowed = false; } if (!allowed) { //set error and return; TRACE() << "ui policy prevented ui launch"; QVariantMap nonConstMap = sessionDataMap; nonConstMap.insert(SSOUI_KEY_ERROR, QUERY_ERROR_FORBIDDEN); processUi(nonConstMap); } else { TRACE() << "open ui"; emit processUiRequest(sessionDataMap); } } else { BLAME() << "Unexpected plugin ui response: "; } } else if (resultOperation == PLUGIN_RESPONSE_REFRESHED) { TRACE() << "PLUGIN_RESPONSE_REFRESHED"; if (!m_isResultObtained) emit processRefreshRequest(sessionDataMap); else BLAME() << "Unexpected plugin ui response: "; } else if (resultOperation == PLUGIN_RESPONSE_ERROR) { TRACE() << "PLUGIN_RESPONSE_ERROR"; quint32 err; QString errorMessage; QDataStream stream(m_process); stream >> err; stream >> errorMessage; m_isProcessing = false; if (!m_isResultObtained) emit processError((int)err, errorMessage); else BLAME() << "Unexpected plugin error: " << errorMessage; m_isResultObtained = true; } else if (resultOperation == PLUGIN_RESPONSE_SIGNAL) { TRACE() << "PLUGIN_RESPONSE_SIGNAL"; quint32 state; QString message; QDataStream stream(m_process); stream >> state; stream >> message; if (!m_isResultObtained) emit stateChanged((int)state, message); else BLAME() << "Unexpected plugin signal: " << state << message; } connect(m_process, SIGNAL(readyRead()), this, SLOT(onReadStandardOutput())); if (m_process->bytesAvailable()) { TRACE() << "plugin has more to read after handling a response"; onReadStandardOutput(); } } void PluginProxy::onReadStandardError() { QString ba = QString::fromLatin1(m_process->readAllStandardError()); } void PluginProxy::onExit(int exitCode, QProcess::ExitStatus exitStatus) { TRACE() << "Plugin process exit with code " << exitCode << " : " << exitStatus; if (m_isProcessing || exitStatus == QProcess::CrashExit) { qCritical() << "Challenge produces CRASH!"; emit processError(Error::InternalServer, QLatin1String("plugin processed crashed")); } if (exitCode == 2) { TRACE() << "plugin process terminated because cannot change user"; } m_isProcessing = false; } void PluginProxy::onError(QProcess::ProcessError err) { TRACE() << "Error: " << err; } QString PluginProxy::queryType() { TRACE(); if (!restartIfRequired()) return QString(); QDataStream ds(m_process); ds << (quint32)PLUGIN_OP_TYPE; QByteArray buffer; bool result; if (!(result = readOnReady(buffer, PLUGINPROCESS_START_TIMEOUT))) qCritical("PluginProxy returned NULL result"); QString type; QDataStream out(buffer); out >> type; return type; } QStringList PluginProxy::queryMechanisms() { TRACE(); if (!restartIfRequired()) return QStringList(); QDataStream in(m_process); in << (quint32)PLUGIN_OP_MECHANISMS; QByteArray buffer; QStringList strList; bool result; if ((result = readOnReady(buffer, PLUGINPROCESS_START_TIMEOUT))) { QVariant mechanismsVar; QDataStream out(buffer); out >> mechanismsVar; QVariantList varList = mechanismsVar.toList(); for (int i = 0; i < varList.count(); i++) strList << varList.at(i).toString(); TRACE() << strList; } else qCritical("PluginProxy returned NULL result"); return strList; } bool PluginProxy::waitForStarted(int timeout) { if (!m_process->waitForStarted(timeout)) return false; m_blobIOHandler = new BlobIOHandler(m_process, m_process, this); connect(m_blobIOHandler, SIGNAL(dataReceived(const QVariantMap &)), this, SLOT(sessionDataReceived(const QVariantMap &))); QSocketNotifier *readNotifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this); readNotifier->setEnabled(false); m_blobIOHandler->setReadChannelSocketNotifier(readNotifier); return true; } bool PluginProxy::waitForFinished(int timeout) { return m_process->waitForFinished(timeout); } bool PluginProxy::restartIfRequired() { if (m_process->state() == QProcess::NotRunning) { TRACE() << "RESTART REQUIRED"; m_process->start(REMOTEPLUGIN_BIN_PATH, QStringList(m_type)); QByteArray tmp; if (!waitForStarted(PLUGINPROCESS_START_TIMEOUT) || !readOnReady(tmp, PLUGINPROCESS_START_TIMEOUT)) return false; } return true; } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signond.pro0000664000175000017500000000525114615454547021500 0ustar coucoufcoucoufinclude( ../../common-project-config.pri ) include( ../../common-vars.pri ) TEMPLATE = app TARGET = signond QT += core \ sql \ xml \ network \ dbus #generate adaptor for backup DBUS_ADAPTORS += \ ../../lib/signond/com.nokia.SingleSignOn.Backup.xml HEADERS += \ accesscontrolmanagerhelper.h \ credentialsaccessmanager.h \ credentialsdb.h \ credentialsdb_p.h \ default-crypto-manager.h \ default-key-authorizer.h \ default-secrets-storage.h \ error.h \ erroradapter.h \ peercontext.h \ signonsessioncore.h \ signonauthsessionadaptor.h \ signonauthsession.h \ signonidentity.h \ signond-common.h \ signondaemonadaptor.h \ signondaemon.h \ signondisposable.h \ signontrace.h \ pluginproxy.h \ signonidentityinfo.h \ signonui_interface.h \ signonidentityadaptor.h \ signonsecuritycontext.h \ signonsessioncoretools.h SOURCES += \ accesscontrolmanagerhelper.cpp \ credentialsaccessmanager.cpp \ credentialsdb.cpp \ default-crypto-manager.cpp \ default-key-authorizer.cpp \ default-secrets-storage.cpp \ erroradaptor.cpp \ signonsessioncore.cpp \ signonauthsessionadaptor.cpp \ signonauthsession.cpp \ signonidentity.cpp \ signondaemonadaptor.cpp \ signondisposable.cpp \ signonui_interface.cpp \ pluginproxy.cpp \ main.cpp \ signondaemon.cpp \ signonidentityinfo.cpp \ signonidentityadaptor.cpp \ signonsecuritycontext.cpp \ signonsessioncoretools.cpp INCLUDEPATH += . \ $${TOP_SRC_DIR}/lib/plugins \ $${TOP_SRC_DIR}/lib/plugins/signon-plugins-common \ $${TOP_SRC_DIR}/lib/signond \ $${TOP_SRC_DIR}/lib/sim-dlc \ $${TOP_SRC_DIR}/lib CONFIG += build_all \ link_pkgconfig QMAKE_LIBDIR += \ $${TOP_BUILD_DIR}/lib/plugins/signon-plugins-common \ $${TOP_BUILD_DIR}/lib/signond/SignOn CONFIG(enable-p2p) { DEFINES += ENABLE_P2P PKGCONFIG += dbus-1 } CONFIG(enable-backup) { DEFINES += ENABLE_BACKUP SOURCES += \ backup.cpp HEADERS += \ backup.h } DEFINES += QT_NO_CAST_TO_ASCII \ QT_NO_CAST_FROM_ASCII DEFINES += "SIGNOND_PLUGINS_DIR=$${SIGNOND_PLUGINS_DIR_QUOTED}" DEFINES += "SIGNOND_EXTENSIONS_DIR=$${SIGNOND_EXTENSIONS_DIR_QUOTED}" #Trace defines can be overruled by signond's configuration file `LoggingLevel` DEFINES += SIGNOND_TRACE LIBS += \ -lrt \ -lsignon-plugins-common \ -lsignon-extension headers.files = $$HEADERS include( ../../common-installs-config.pri ) !no_etc { OTHER_FILES += \ signond.conf \ setupstorage.sh conf_file.files = $$OTHER_FILES conf_file.path = /etc/ INSTALLS += conf_file } signond-nicolasfella/src/signond/signondaemonadaptor.cpp0000664000175000017500000002362014615454547024055 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signondaemonadaptor.h" #include "signonauthsessionadaptor.h" #include "signondisposable.h" #include "signonidentityadaptor.h" #include "accesscontrolmanagerhelper.h" namespace SignonDaemonNS { SignonDaemonAdaptor::SignonDaemonAdaptor(SignonDaemon *parent): QDBusAbstractAdaptor(parent), m_parent(parent) { setAutoRelaySignals(false); } SignonDaemonAdaptor::~SignonDaemonAdaptor() { } template QDBusObjectPath SignonDaemonAdaptor::registerObject(const QDBusConnection &connection, T *object) { QString path = object->objectName(); QObject *registeredObject = connection.objectRegisteredAt(path); if (!registeredObject || registeredObject->parent() != object) { QDBusConnection conn(connection); auto adaptor = new typename T::Adaptor(object); if (!conn.registerObject(path, adaptor, QDBusConnection::ExportAllContents)) { BLAME() << "Object registration failed:" << object << conn.lastError(); } } return QDBusObjectPath(path); } QDBusObjectPath SignonDaemonAdaptor::registerNewIdentity(const QString &applicationContext) { Q_UNUSED(applicationContext); SignonIdentity *identity = m_parent->registerNewIdentity(); QDBusConnection dbusConnection(parentDBusContext().connection()); QDBusObjectPath objectPath = registerObject(dbusConnection, identity); SignonDisposable::destroyUnused(); return objectPath; } void SignonDaemonAdaptor::securityErrorReply() { securityErrorReply(parentDBusContext().connection(), parentDBusContext().message()); } void SignonDaemonAdaptor::securityErrorReply(const QDBusConnection &conn, const QDBusMessage &msg) { QString errMsg; QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR << "Method:" << msg.member(); msg.setDelayedReply(true); QDBusMessage errReply = msg.createErrorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME, errMsg); conn.send(errReply); TRACE() << "Method FAILED Access Control check:" << msg.member(); } bool SignonDaemonAdaptor::handleLastError(const QDBusConnection &conn, const QDBusMessage &msg) { if (!m_parent->lastErrorIsValid()) return false; msg.setDelayedReply(true); QDBusMessage errReply = msg.createErrorReply(m_parent->lastErrorName(), m_parent->lastErrorMessage()); conn.send(errReply); return true; } void SignonDaemonAdaptor::getIdentity(const quint32 id, const QString &applicationContext, QDBusObjectPath &objectPath, QVariantMap &identityData) { Q_UNUSED(applicationContext); AccessControlManagerHelper *acm = AccessControlManagerHelper::instance(); QDBusMessage msg = parentDBusContext().message(); QDBusConnection conn = parentDBusContext().connection(); if (!acm->isPeerAllowedToUseIdentity(PeerContext(conn, msg), id)) { SignOn::AccessReply *reply = acm->requestAccessToIdentity(PeerContext(conn, msg), id); QObject::connect(reply, SIGNAL(finished()), this, SLOT(onIdentityAccessReplyFinished())); msg.setDelayedReply(true); return; } SignonIdentity *identity = m_parent->getIdentity(id, identityData); if (handleLastError(conn, msg)) return; objectPath = registerObject(conn, identity); SignonDisposable::destroyUnused(); } void SignonDaemonAdaptor::onIdentityAccessReplyFinished() { SignOn::AccessReply *reply = qobject_cast(sender()); Q_ASSERT(reply != 0); reply->deleteLater(); QDBusConnection connection = reply->request().peerConnection(); QDBusMessage message = reply->request().peerMessage(); quint32 id = reply->request().identity(); AccessControlManagerHelper *acm = AccessControlManagerHelper::instance(); if (!reply->isAccepted() || !acm->isPeerAllowedToUseIdentity(PeerContext(connection, message), id)) { securityErrorReply(connection, message); return; } QVariantMap identityData; SignonIdentity *identity = m_parent->getIdentity(id, identityData); if (handleLastError(connection, message)) return; QDBusObjectPath objectPath = registerObject(connection, identity); QVariantList args; args << QVariant::fromValue(objectPath); args << identityData; connection.send(message.createReply(args)); SignonDisposable::destroyUnused(); } QStringList SignonDaemonAdaptor::queryMethods() { return m_parent->queryMethods(); } QDBusObjectPath SignonDaemonAdaptor::getAuthSessionObjectPath(const quint32 id, const QString &applicationContext, const QString &type) { Q_UNUSED(applicationContext); SignonDisposable::destroyUnused(); AccessControlManagerHelper *acm = AccessControlManagerHelper::instance(); QDBusMessage msg = parentDBusContext().message(); QDBusConnection conn = parentDBusContext().connection(); /* Access Control */ if (id != SIGNOND_NEW_IDENTITY) { if (!acm->isPeerAllowedToUseIdentity(PeerContext(conn, msg), id)) { SignOn::AccessReply *reply = acm->requestAccessToIdentity(PeerContext(conn, msg), id); /* If the request is accepted, we'll need the method name ("type") * in order to proceed with the creation of the authsession. */ reply->setProperty("type", type); QObject::connect(reply, SIGNAL(finished()), this, SLOT(onAuthSessionAccessReplyFinished())); msg.setDelayedReply(true); return QDBusObjectPath(); } } TRACE() << "ACM passed, creating AuthSession object"; pid_t ownerPid = acm->pidOfPeer(PeerContext(conn, msg)); SignonAuthSession *authSession = m_parent->getAuthSession(id, type, ownerPid); if (handleLastError(conn, msg)) return QDBusObjectPath(); return registerObject(conn, authSession); } void SignonDaemonAdaptor::onAuthSessionAccessReplyFinished() { SignOn::AccessReply *reply = qobject_cast(sender()); Q_ASSERT(reply != 0); reply->deleteLater(); QDBusConnection connection = reply->request().peerConnection(); QDBusMessage message = reply->request().peerMessage(); quint32 id = reply->request().identity(); QString type = reply->property("type").toString(); AccessControlManagerHelper *acm = AccessControlManagerHelper::instance(); if (!reply->isAccepted() || !acm->isPeerAllowedToUseIdentity(PeerContext(connection, message), id)) { securityErrorReply(connection, message); TRACE() << "still not allowed"; return; } pid_t ownerPid = acm->pidOfPeer(PeerContext(connection, message)); SignonAuthSession *authSession = m_parent->getAuthSession(id, type, ownerPid); if (handleLastError(connection, message)) return; QDBusObjectPath objectPath = registerObject(connection, authSession); QVariantList args; args << QVariant::fromValue(objectPath); connection.send(message.createReply(args)); SignonDisposable::destroyUnused(); } QStringList SignonDaemonAdaptor::queryMechanisms(const QString &method) { QStringList mechanisms = m_parent->queryMechanisms(method); if (handleLastError(parentDBusContext().connection(), parentDBusContext().message())) { return QStringList(); } return mechanisms; } void SignonDaemonAdaptor::queryIdentities(const QVariantMap &filter, const QString &applicationContext) { Q_UNUSED(applicationContext); /* Access Control */ QDBusMessage msg = parentDBusContext().message(); QDBusConnection conn = parentDBusContext().connection(); if (!AccessControlManagerHelper::instance()->isPeerKeychainWidget( PeerContext(conn, msg))) { securityErrorReply(); return; } msg.setDelayedReply(true); MapList identities = m_parent->queryIdentities(filter); if (handleLastError(conn, msg)) return; QDBusMessage reply = msg.createReply(QVariant::fromValue(identities)); conn.send(reply); } bool SignonDaemonAdaptor::clear() { /* Access Control */ QDBusMessage msg = parentDBusContext().message(); QDBusConnection conn = parentDBusContext().connection(); if (!AccessControlManagerHelper::instance()->isPeerKeychainWidget( PeerContext(conn, msg))) { securityErrorReply(); return false; } bool ok = m_parent->clear(); if (handleLastError(conn, msg)) return false; return ok; } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signondaemonadaptor.h0000664000175000017500000000547714615454547023534 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNONDAEMONADAPTER_H_ #define SIGNONDAEMONADAPTER_H_ #include #include #include "signond-common.h" #include "signondaemon.h" namespace SignonDaemonNS { typedef QList MapList; class SignonDaemonAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "com.google.code.AccountsSSO.SingleSignOn.AuthService") public: SignonDaemonAdaptor(SignonDaemon *parent); virtual ~SignonDaemonAdaptor(); inline const QDBusContext &parentDBusContext() const { return *static_cast(m_parent); } public Q_SLOTS: QDBusObjectPath registerNewIdentity(const QString &applicationContext); void getIdentity(const quint32 id, const QString &applicationContext, QDBusObjectPath &objectPath, QVariantMap &identityData); QDBusObjectPath getAuthSessionObjectPath(const quint32 id, const QString &applicationContext, const QString &type); QStringList queryMethods(); QStringList queryMechanisms(const QString &method); void queryIdentities(const QVariantMap &filter, const QString &applicationContext); bool clear(); private: void securityErrorReply(); void securityErrorReply(const QDBusConnection &connection, const QDBusMessage &message); bool handleLastError(const QDBusConnection &connection, const QDBusMessage &message); template QDBusObjectPath registerObject(const QDBusConnection &connection, T *object); private Q_SLOTS: void onIdentityAccessReplyFinished(); void onAuthSessionAccessReplyFinished(); private: SignonDaemon *m_parent; }; //class SignonDaemonAdaptor } //namespace SignonDaemonNS Q_DECLARE_METATYPE(SignonDaemonNS::MapList) #endif /* SIGNONDAEMONADAPTER_H_ */ signond-nicolasfella/src/signond/signonidentity.cpp0000664000175000017500000004670314615454547023077 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signonidentity.h" #include "error.h" #include "signond-common.h" #include "signonui_interface.h" #include "SignOn/uisessiondata.h" #include "SignOn/uisessiondata_priv.h" #include "signoncommon.h" #include "accesscontrolmanagerhelper.h" #include #include #include #include #define SIGNON_RETURN_IF_CAM_NOT_AVAILABLE_ASYNC0() \ if (!(CredentialsAccessManager::instance()->credentialsSystemOpened())) { \ Error error = \ Error(Error::InternalServer, \ internalServerErrStr + \ QLatin1String("Could not access Signon Database."));\ callback(error); \ return; \ } #define SIGNON_RETURN_IF_CAM_NOT_AVAILABLE_ASYNC1(ret) \ if (!(CredentialsAccessManager::instance()->credentialsSystemOpened())) { \ Error error = \ Error(Error::InternalServer, \ internalServerErrStr + \ QLatin1String("Could not access Signon Database."));\ callback(ret, error); \ return; \ } #define SIGNON_RETURN_IF_CAM_NOT_AVAILABLE() do { \ if (!(CredentialsAccessManager::instance()->credentialsSystemOpened())) { \ return Error(Error::InternalServer, \ internalServerErrStr + \ QLatin1String("Could not access Signon Database.")); \ } \ } while(0) namespace SignonDaemonNS { const QString internalServerErrStr = SIGNOND_INTERNAL_SERVER_ERR_STR; SignonIdentity::SignonIdentity(quint32 id, int timeout, SignonDaemon *parent): SignonDisposable(timeout, parent), m_pInfo(NULL), m_destroyed(false) { m_id = id; /* * creation of unique name for the given identity * */ static quint32 incr = 0; QString objectName = SIGNOND_DAEMON_OBJECTPATH + QLatin1String("/Identity_") + QString::number(incr++, 16); setObjectName(objectName); m_signonui = new SignonUiAdaptor(SIGNON_UI_SERVICE, SIGNON_UI_DAEMON_OBJECTPATH, QDBusConnection::sessionBus(), this); /* Watch for credential updates happening outside of this object (this can * happen on request of authentication plugins) */ CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); QObject::connect(db, SIGNAL(credentialsUpdated(quint32)), this, SLOT(onCredentialsUpdated(quint32))); } SignonIdentity::~SignonIdentity() { if (!m_destroyed) { m_destroyed = true; Q_EMIT unregistered(); } delete m_signonui; delete m_pInfo; } SignonIdentity *SignonIdentity::createIdentity(quint32 id, SignonDaemon *parent) { return new SignonIdentity(id, parent->identityTimeout(), parent); } void SignonIdentity::destroy() { m_destroyed = true; Q_EMIT unregistered(); deleteLater(); } SignonIdentityInfo SignonIdentity::queryInfo(bool &ok, bool queryPassword) { ok = true; bool needLoadFromDB = true; if (m_pInfo) { needLoadFromDB = false; if (queryPassword && m_pInfo->password().isEmpty()) { needLoadFromDB = true; } } if (needLoadFromDB) { if (m_pInfo != 0) { delete m_pInfo; } CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); m_pInfo = new SignonIdentityInfo(db->credentials(m_id, queryPassword)); if (db->lastError().isValid()) { ok = false; delete m_pInfo; m_pInfo = NULL; return SignonIdentityInfo(); } } /* Make sure that we clear the password, if the caller doesn't need it */ SignonIdentityInfo info = *m_pInfo; if (!queryPassword) { info.setPassword(QString()); } return info; } Error SignonIdentity::addReference(const QString &reference, const QString &appId) { TRACE() << "addReference: " << reference; SIGNON_RETURN_IF_CAM_NOT_AVAILABLE(); CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if (db == NULL) { BLAME() << "NULL database handler object."; return Error::InternalServer; } keepInUse(); bool ok = db->addReference(m_id, appId, reference); return ok ? Error::NoError : Error::OperationFailed; } Error SignonIdentity::removeReference(const QString &reference, const QString &appId) { TRACE() << "removeReference: " << reference; SIGNON_RETURN_IF_CAM_NOT_AVAILABLE(); CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if (db == NULL) { BLAME() << "NULL database handler object."; return Error::InternalServer; } keepInUse(); bool ok = db->removeReference(m_id, appId, reference); return ok ? Error::NoError : Error::OperationFailed; } void SignonIdentity::requestCredentialsUpdate(const QString &displayMessage, const CredentialsUpdateCb &callback) { SIGNON_RETURN_IF_CAM_NOT_AVAILABLE_ASYNC1(SIGNOND_NEW_IDENTITY); bool ok; SignonIdentityInfo info = queryInfo(ok, false); if (!ok) { BLAME() << "Identity not found."; callback(SIGNOND_NEW_IDENTITY, Error(Error::IdentityNotFound)); return; } if (!info.storePassword()) { BLAME() << "Password cannot be stored."; callback(SIGNOND_NEW_IDENTITY, Error(Error::StoreFailed)); return; } //create ui request to ask password QVariantMap uiRequest; uiRequest.insert(SSOUI_KEY_QUERYPASSWORD, true); uiRequest.insert(SSOUI_KEY_USERNAME, info.userName()); uiRequest.insert(SSOUI_KEY_MESSAGE, displayMessage); uiRequest.insert(SSOUI_KEY_CAPTION, info.caption()); TRACE() << "Waiting for reply from signon-ui"; QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(m_signonui->queryDialog(uiRequest), this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher, callback]() { queryUiSlot(watcher, callback); }); setAutoDestruct(false); } Error SignonIdentity::getInfo(SignonIdentityInfo *info) { TRACE() << "QUERYING INFO"; SIGNON_RETURN_IF_CAM_NOT_AVAILABLE(); bool ok; *info = queryInfo(ok, false); info->removeSecrets(); if (!ok) { TRACE(); return Error(Error::CredentialsNotAvailable, SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR + QLatin1String("Database querying error occurred.")); } if (info->isNew()) { TRACE(); return Error::IdentityNotFound; } keepInUse(); return Error::NoError; } void SignonIdentity::queryUserPassword(const QVariantMap ¶ms, const VerifyUserCb &callback) { TRACE() << "Waiting for reply from signon-ui"; QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(m_signonui->queryDialog(params), this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher, callback]() { verifyUiSlot(watcher, callback); }); setAutoDestruct(false); } void SignonIdentity::verifyUser(const QVariantMap ¶ms, const VerifyUserCb &callback) { SIGNON_RETURN_IF_CAM_NOT_AVAILABLE_ASYNC1(false); bool ok; SignonIdentityInfo info = queryInfo(ok, true); if (!ok) { BLAME() << "Identity not found."; callback(false, Error(Error::IdentityNotFound)); return; } if (!info.storePassword() || info.password().isEmpty()) { BLAME() << "Password is not stored."; callback(false, Error(Error::CredentialsNotAvailable)); return; } //create ui request to ask password QVariantMap uiRequest = params; uiRequest.insert(SSOUI_KEY_QUERYPASSWORD, true); uiRequest.insert(SSOUI_KEY_USERNAME, info.userName()); uiRequest.insert(SSOUI_KEY_CAPTION, info.caption()); queryUserPassword(uiRequest, callback); } Error SignonIdentity::verifySecret(const QString &secret, bool *verified) { SIGNON_RETURN_IF_CAM_NOT_AVAILABLE(); bool ok; queryInfo(ok); if (!ok) { TRACE(); return Error(Error::CredentialsNotAvailable, SIGNOND_CREDENTIALS_NOT_AVAILABLE_ERR_STR + QLatin1String("Database querying error occurred.")); } CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); *verified = db->checkPassword(m_pInfo->id(), m_pInfo->userName(), secret); keepInUse(); return Error::NoError; } void SignonIdentity::remove(const RemoveCb &callback) { SIGNON_RETURN_IF_CAM_NOT_AVAILABLE_ASYNC0(); CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if ((db == 0) || !db->removeCredentials(m_id)) { TRACE() << "Error occurred while inserting/updating credentials."; callback(Error(Error::RemoveFailed, SIGNOND_REMOVE_FAILED_ERR_STR + QLatin1String("Database error occurred."))); return; } setAutoDestruct(false); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(m_signonui->removeIdentityData(m_id), this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher, callback]() { removeCompleted(watcher, callback); }); keepInUse(); } void SignonIdentity::removeCompleted(QDBusPendingCallWatcher *call, const RemoveCb &callback) { Q_ASSERT(call != NULL); setAutoDestruct(true); call->deleteLater(); QDBusPendingReply<> signOnUiReply = *call; bool ok = !signOnUiReply.isError(); TRACE() << (ok ? "removeIdentityData succeeded" : "removeIdentityData failed"); emit infoUpdated((int)SignOn::IdentityRemoved); callback(Error::none()); } void SignonIdentity::signOut(const SignOutCb &callback) { TRACE() << "Signout request. Identity ID: " << id(); /* * - If the identity is stored (thus registered here) * signal 'sign out' to all identities subsribed to this object, * otherwise the only identity subscribed to this is the newly * created client side identity, which called this method. * - This is just a safety check, as the client identity - if it is a new * one - should not inform server side to sign out. */ if (id() != SIGNOND_NEW_IDENTITY) { //clear stored sessiondata CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if ((db == 0) || !db->removeData(m_id)) { TRACE() << "clear data failed"; } setAutoDestruct(false); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(m_signonui->removeIdentityData(m_id), this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher, callback]() { signOutCompleted(watcher, callback); }); } keepInUse(); } void SignonIdentity::signOutCompleted(QDBusPendingCallWatcher *call, const SignOutCb &callback) { Q_ASSERT(call != NULL); setAutoDestruct(true); call->deleteLater(); QDBusPendingReply<> signOnUiReply = *call; bool ok = !signOnUiReply.isError(); TRACE() << (ok ? "removeIdentityData succeeded" : "removeIdentityData failed"); emit infoUpdated((int)SignOn::IdentitySignedOut); callback(ok, Error::none()); } void SignonIdentity::onCredentialsUpdated(quint32 id) { if (id != m_id) return; TRACE() << m_id; /* Clear the cached information about the identity; some of it might not be * valid anymore */ if (m_pInfo) { delete m_pInfo; m_pInfo = NULL; } emit infoUpdated((int)SignOn::IdentityDataUpdated); } Error SignonIdentity::store(const QVariantMap &info, const QString &appId, quint32 *id) { keepInUse(); SIGNON_RETURN_IF_CAM_NOT_AVAILABLE(); const QVariant container = info.value(SIGNOND_IDENTITY_INFO_AUTHMETHODS); MethodMap methods = container.isValid() ? qdbus_cast(container.value()) : MethodMap(); if (m_pInfo == 0) { m_pInfo = new SignonIdentityInfo(info); m_pInfo->setMethods(methods); //Add creator to owner list if it has AID QStringList ownerList = info.value(SIGNOND_IDENTITY_INFO_OWNER).toStringList(); if (!appId.isNull()) { ownerList.append(appId); } m_pInfo->setOwnerList(ownerList); } else { SignonIdentityInfo newInfo(info); m_pInfo->update(newInfo); } m_id = storeCredentials(*m_pInfo); *id = m_id; return m_id == SIGNOND_NEW_IDENTITY ? Error::StoreFailed : Error::NoError; } quint32 SignonIdentity::storeCredentials(const SignonIdentityInfo &info) { CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if (db == NULL) { BLAME() << "NULL database handler object."; return SIGNOND_NEW_IDENTITY; } bool newIdentity = info.isNew(); if (newIdentity) m_id = db->insertCredentials(info); else db->updateCredentials(info); if (db->errorOccurred()) { if (newIdentity) m_id = SIGNOND_NEW_IDENTITY; TRACE() << "Error occurred while inserting/updating credentials."; } else { if (m_pInfo) { delete m_pInfo; m_pInfo = NULL; } Q_EMIT stored(this); TRACE() << "FRESH, JUST STORED CREDENTIALS ID:" << m_id; emit infoUpdated((int)SignOn::IdentityDataUpdated); } return m_id; } void SignonIdentity::queryUiSlot(QDBusPendingCallWatcher *call, const CredentialsUpdateCb &callback) { TRACE(); Q_ASSERT(call != NULL); setAutoDestruct(true); QDBusMessage errReply; QDBusPendingReply reply = *call; call->deleteLater(); QVariantMap resultParameters; if (!reply.isError() && reply.count()) { resultParameters = reply.argumentAt<0>(); } else { callback(0, Error(Error::OperationCanceled)); return; } if (!resultParameters.contains(SSOUI_KEY_ERROR)) { //no reply code callback(0, Error(Error::InternalServer)); return; } int errorCode = resultParameters.value(SSOUI_KEY_ERROR).toInt(); TRACE() << "error: " << errorCode; if (errorCode != QUERY_ERROR_NONE) { Error error; if (errorCode == QUERY_ERROR_CANCELED) { error = Error(Error::OperationCanceled); } else { error = Error(Error::InternalServer, QString(QLatin1String("signon-ui call returned error %1")). arg(errorCode)); } callback(0, error); return; } if (resultParameters.contains(SSOUI_KEY_PASSWORD)) { CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if (db == NULL) { BLAME() << "NULL database handler object."; callback(0, Error(Error::StoreFailed)); return; } //store new password if (m_pInfo) { m_pInfo->setPassword(resultParameters[SSOUI_KEY_PASSWORD].toString()); quint32 ret = db->updateCredentials(*m_pInfo); delete m_pInfo; m_pInfo = NULL; if (ret != SIGNOND_NEW_IDENTITY) { callback(m_id, Error::none()); return; } else{ BLAME() << "Error during update"; } } } //this should not happen, return error callback(0, Error(Error::InternalServer)); return; } void SignonIdentity::verifyUiSlot(QDBusPendingCallWatcher *call, const VerifyUserCb &callback) { TRACE(); Q_ASSERT(call != NULL); setAutoDestruct(true); QDBusMessage errReply; QDBusPendingReply reply = *call; call->deleteLater(); QVariantMap resultParameters; if (!reply.isError() && reply.count()) { resultParameters = reply.argumentAt<0>(); } else { callback(false, Error(Error::OperationCanceled)); return; } if (!resultParameters.contains(SSOUI_KEY_ERROR)) { //no reply code callback(false, Error(Error::InternalServer)); return; } int errorCode = resultParameters.value(SSOUI_KEY_ERROR).toInt(); TRACE() << "error: " << errorCode; if (errorCode != QUERY_ERROR_NONE) { Error error; if (errorCode == QUERY_ERROR_CANCELED) { error = Error(Error::OperationCanceled); } else if (errorCode == QUERY_ERROR_FORGOT_PASSWORD) { error = Error(Error::ForgotPassword); } else { error = Error(Error::InternalServer, QString(QLatin1String("signon-ui call " "returned error %1")). arg(errorCode)); } callback(false, error); return; } if (resultParameters.contains(SSOUI_KEY_PASSWORD)) { CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); if (db == NULL) { BLAME() << "NULL database handler object."; callback(false, Error(Error::StoreFailed)); return; } //compare passwords if (m_pInfo) { bool ret = m_pInfo->password() == resultParameters[SSOUI_KEY_PASSWORD]. toString(); if (!ret && resultParameters.contains(SSOUI_KEY_CONFIRMCOUNT)) { int count = resultParameters[SSOUI_KEY_CONFIRMCOUNT].toInt(); TRACE() << "retry count:" << count; if (count > 0) { //retry resultParameters[SSOUI_KEY_CONFIRMCOUNT] = (count-1); resultParameters[SSOUI_KEY_MESSAGEID] = QUERY_MESSAGE_NOT_AUTHORIZED; queryUserPassword(resultParameters, callback); return; } else { //TODO show error note here if needed } } delete m_pInfo; m_pInfo = NULL; callback(ret, Error::none()); return; } } //this should not happen, return error callback(false, Error(Error::InternalServer)); return; } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signonidentityinfo.cpp0000664000175000017500000001020314615454547023735 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signond-common.h" #include "signonidentityinfo.h" #include #include #include #include #include namespace SignonDaemonNS { SignonIdentityInfo::SignonIdentityInfo() { } SignonIdentityInfo::SignonIdentityInfo(const QVariantMap &info) { /* We need to expand any QDBusArguments which might be present, since * the map is likely to be coming from QDBus. */ QVariantMap::const_iterator i; for (i = info.constBegin(); i != info.constEnd(); i++) { if (qstrcmp(i.value().typeName(), "QDBusArgument") == 0) { QDBusArgument container = i.value().value(); if (i.key() == SIGNOND_IDENTITY_INFO_AUTHMETHODS) { MethodMap methodMap = qdbus_cast(container); setMethods(methodMap); } else if (i.key() == SIGNOND_IDENTITY_INFO_ACL) { SignonSecurityContextList accessControlList = qdbus_cast(container); setAccessControlList(accessControlList); } else { BLAME() << "Found unsupported QDBusArgument in key" << i.key(); } } else { insert(i.key(), i.value()); } } } const QVariantMap SignonIdentityInfo::toMap() const { return *this; } void SignonIdentityInfo::update(const SignonIdentityInfo &info) { QMapIterator it(info); while (it.hasNext()) { it.next(); // We don't allow updating the ID if (it.key() == SIGNOND_IDENTITY_INFO_ID) continue; insert(it.key(), it.value()); } } bool SignonIdentityInfo::checkMethodAndMechanism(const QString &method, const QString &mechanism, QString &allowedMechanism) { MethodMap methodMap = methods(); // If no methods have been specified for an identity assume anything goes if (methodMap.isEmpty()) return true; if (!methodMap.contains(method)) return false; MechanismsList mechs = methodMap[method]; // If no mechanisms have been specified for a method, assume anything goes if (mechs.isEmpty()) return true; if (mechs.contains(mechanism)) { allowedMechanism = mechanism; return true; } /* in the case of SASL authentication (and possibly others), * mechanism can be a list of strings, separated by a space; * therefore, let's split the list first, and see if any of the * mechanisms is allowed. */ QStringList mechanisms = #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) mechanism.split(QLatin1Char(' '), Qt::SkipEmptyParts); #else mechanism.split(QLatin1Char(' '), QString::SkipEmptyParts); #endif /* if the list is empty of it has only one element, then we already know * that it didn't pass the previous checks */ if (mechanisms.size() <= 1) return false; QStringList allowedMechanisms; foreach (const QString &mech, mechanisms) { if (mechs.contains(mech)) allowedMechanisms.append(mech); } if (allowedMechanisms.isEmpty()) return false; allowedMechanism = allowedMechanisms.join(QLatin1String(" ")); return true; } } //namespace SignonDaemonNS signond-nicolasfella/src/signond/signonsessioncore.cpp0000664000175000017500000007003514615454547023575 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2011 Intel Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * Contact: Jussi Laako * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "erroradaptor.h" #include "signond-common.h" #include "signonauthsession.h" #include "signonidentityinfo.h" #include "signonidentity.h" #include "signonui_interface.h" #include "accesscontrolmanagerhelper.h" #include "SignOn/uisessiondata_priv.h" #include "SignOn/authpluginif.h" #include "SignOn/signonerror.h" #define MAX_IDLE_TIME SIGNOND_MAX_IDLE_TIME /* * the watchdog searches for idle sessions with period of half of idle timeout * */ #define IDLE_WATCHDOG_TIMEOUT SIGNOND_MAX_IDLE_TIME * 500 #define SSO_KEY_USERNAME QLatin1String("UserName") #define SSO_KEY_PASSWORD QLatin1String("Secret") #define SSO_KEY_CAPTION QLatin1String("Caption") using namespace SignonDaemonNS; /* * cache of session queues, as was mentined they cannot be static * */ QMap sessionsOfStoredCredentials; /* * List of "zero" authsessions, needed for global signout * */ QList sessionsOfNonStoredCredentials; static QVariantMap filterVariantMap(const QVariantMap &other) { QVariantMap result; foreach(QString key, other.keys()) { if (!other.value(key).isNull() && other.value(key).isValid()) result.insert(key, other.value(key)); } return result; } static QString sessionName(const quint32 id, const QString &method) { return QString::number(id) + QLatin1String("+") + method; } SignonSessionCore::SignonSessionCore(quint32 id, const QString &method, int timeout, QObject *parent): SignonDisposable(timeout, parent), m_signonui(0), m_watcher(0), m_requestIsActive(false), m_canceled(false), m_id(id), m_method(method), m_queryCredsUiDisplayed(false) { m_signonui = new SignonUiAdaptor(SIGNON_UI_SERVICE, SIGNON_UI_DAEMON_OBJECTPATH, QDBusConnection::sessionBus()); connect(CredentialsAccessManager::instance(), SIGNAL(credentialsSystemReady()), SLOT(credentialsSystemReady())); } SignonSessionCore::~SignonSessionCore() { delete m_plugin; delete m_watcher; delete m_signonui; m_plugin = NULL; m_signonui = NULL; m_watcher = NULL; } SignonSessionCore *SignonSessionCore::sessionCore(const quint32 id, const QString &method, SignonDaemon *parent) { QString key = sessionName(id, method); if (id) { if (sessionsOfStoredCredentials.contains(key)) { return sessionsOfStoredCredentials.value(key); } } SignonSessionCore *ssc = new SignonSessionCore(id, method, parent->authSessionTimeout(), parent); if (ssc->setupPlugin() == false) { TRACE() << "The resulted object is corrupted and has to be deleted"; delete ssc; return NULL; } if (id) sessionsOfStoredCredentials.insert(key, ssc); else sessionsOfNonStoredCredentials.append(ssc); TRACE() << "The new session is created :" << key; return ssc; } quint32 SignonSessionCore::id() const { TRACE(); keepInUse(); return m_id; } QString SignonSessionCore::method() const { TRACE(); keepInUse(); return m_method; } bool SignonSessionCore::setupPlugin() { m_plugin = PluginProxy::createNewPluginProxy(m_method); if (!m_plugin) { TRACE() << "Plugin of type " << m_method << " cannot be found"; return false; } connect(m_plugin, SIGNAL(processResultReply(const QVariantMap&)), this, SLOT(processResultReply(const QVariantMap&)), Qt::DirectConnection); connect(m_plugin, SIGNAL(processStore(const QVariantMap&)), this, SLOT(processStore(const QVariantMap&)), Qt::DirectConnection); connect(m_plugin, SIGNAL(processUiRequest(const QVariantMap&)), this, SLOT(processUiRequest(const QVariantMap&)), Qt::DirectConnection); connect(m_plugin, SIGNAL(processRefreshRequest(const QVariantMap&)), this, SLOT(processRefreshRequest(const QVariantMap&)), Qt::DirectConnection); connect(m_plugin, SIGNAL(processError(int, const QString&)), this, SLOT(processError(int, const QString&)), Qt::DirectConnection); connect(m_plugin, SIGNAL(stateChanged(int, const QString&)), this, SLOT(stateChangedSlot(int, const QString&)), Qt::DirectConnection); return true; } void SignonSessionCore::stopAllAuthSessions() { qDeleteAll(sessionsOfStoredCredentials); sessionsOfStoredCredentials.clear(); qDeleteAll(sessionsOfNonStoredCredentials); sessionsOfNonStoredCredentials.clear(); } QStringList SignonSessionCore::queryAvailableMechanisms(const QStringList &wantedMechanisms) { keepInUse(); if (!wantedMechanisms.size()) return m_plugin->mechanisms(); const QStringList mechanisms = m_plugin->mechanisms(); #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) QSet mechanismSet(mechanisms.begin(), mechanisms.end()); QSet wantedMechanismSet(wantedMechanisms.begin(), wantedMechanisms.end()); #else QSet mechanismSet = mechanisms.toSet(); QSet wantedMechanismSet = wantedMechanisms.toSet(); #endif return mechanismSet.intersect(wantedMechanismSet).values(); } void SignonSessionCore::process(const PeerContext &peerContext, const QVariantMap &sessionDataVa, const QString &mechanism, const QString &cancelKey, const ProcessCb &callback) { keepInUse(); m_listOfRequests.enqueue(RequestData(peerContext, sessionDataVa, mechanism, cancelKey, callback)); if (CredentialsAccessManager::instance()->isCredentialsSystemReady()) QMetaObject::invokeMethod(this, "startNewRequest", Qt::QueuedConnection); } void SignonSessionCore::cancel(const QString &cancelKey) { TRACE(); int requestIndex; for (requestIndex = 0; requestIndex < m_listOfRequests.size(); requestIndex++) { if (m_listOfRequests.at(requestIndex).m_cancelKey == cancelKey) break; } TRACE() << "The request is found with index " << requestIndex; if (requestIndex < m_listOfRequests.size()) { /* If the request being cancelled is active, we need to keep * in the queue until the plugin has replied. */ bool isActive = (requestIndex == 0) && m_requestIsActive; if (isActive) { m_canceled = true; m_plugin->cancel(); if (m_watcher && !m_watcher->isFinished()) { m_signonui->cancelUiRequest(cancelKey); delete m_watcher; m_watcher = 0; } } /* * We must let to the m_listOfRequests to have the canceled request data * in order to delay the next request execution until the actual cancelation * will happen. We will know about that precisely: plugin must reply via * resultSlot or via errorSlot. * */ RequestData rd(isActive ? m_listOfRequests.head() : m_listOfRequests.takeAt(requestIndex)); rd.m_callback(QVariantMap(), Error::SessionCanceled); TRACE() << "Size of the queue is" << m_listOfRequests.size(); } } void SignonSessionCore::setId(quint32 id) { keepInUse(); if (m_id == id) return; QString key; if (id == 0) { key = sessionName(m_id, m_method); sessionsOfNonStoredCredentials.append( sessionsOfStoredCredentials.take(key)); } else { key = sessionName(id, m_method); if (sessionsOfStoredCredentials.contains(key)) { qCritical() << "attempt to assign existing id"; return; } sessionsOfNonStoredCredentials.removeOne(this); sessionsOfStoredCredentials[key] = this; } m_id = id; } void SignonSessionCore::startProcess() { TRACE() << "the number of requests is" << m_listOfRequests.length(); m_requestIsActive = true; RequestData data = m_listOfRequests.head(); QVariantMap parameters = data.m_params; /* save the client data; this should not be modified during the processing * of this request */ m_clientData = parameters; if (m_id) { CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); Q_ASSERT(db != 0); SignonIdentityInfo info = db->credentials(m_id); if (info.id() != SIGNOND_NEW_IDENTITY) { if (!parameters.contains(SSO_KEY_PASSWORD)) { parameters[SSO_KEY_PASSWORD] = info.password(); } //database overrules over sessiondata for validated username, //so that identity cannot be misused if (info.validated() || !parameters.contains(SSO_KEY_USERNAME)) { parameters[SSO_KEY_USERNAME] = info.userName(); } QStringList paramsTokenList; QStringList identityAclList = info.accessControlList(); foreach(QString acl, identityAclList) { if (AccessControlManagerHelper::instance()-> isPeerAllowedToAccess(data.m_peerContext, acl)) paramsTokenList.append(acl); } if (!paramsTokenList.isEmpty()) { parameters[SSO_ACCESS_CONTROL_TOKENS] = paramsTokenList; } } else { BLAME() << "Error occurred while getting data from credentials " "database."; } QVariantMap storedParams = db->loadData(m_id, m_method); //parameters will overwrite any common keys on stored params parameters = mergeVariantMaps(storedParams, parameters); } if (parameters.contains(SSOUI_KEY_UIPOLICY) && parameters[SSOUI_KEY_UIPOLICY] == RequestPasswordPolicy) { parameters.remove(SSO_KEY_PASSWORD); } /* Temporary caching, if credentials are valid * this data will be effectively cached */ m_tmpUsername = parameters[SSO_KEY_USERNAME].toString(); m_tmpPassword = parameters[SSO_KEY_PASSWORD].toString(); if (!m_plugin->process(parameters, data.m_mechanism)) { data.m_callback(QVariantMap(), Error::RuntimeError); requestDone(); } else stateChangedSlot(SignOn::SessionStarted, QLatin1String("The request is started successfully")); } void SignonSessionCore::replyError(const RequestData &request, int err, const QString &message) { keepInUse(); QString errMessage; using LibErrorCode = SignOn::Error; Error::Code code = Error::NoError; //TODO this is needed for old error codes if (err < LibErrorCode::AuthSessionErr) { BLAME() << "Deprecated error code:" << err; code = Error::UnknownError; errMessage = message; } if (LibErrorCode::AuthSessionErr < err && err < LibErrorCode::UserErr) { switch(err) { case LibErrorCode::MechanismNotAvailable: code = Error::MechanismNotAvailable; break; case LibErrorCode::MissingData: code = Error::MissingData; break; case LibErrorCode::InvalidCredentials: code = Error::InvalidCredentials; break; case LibErrorCode::NotAuthorized: code = Error::NotAuthorized; break; case LibErrorCode::WrongState: code = Error::WrongState; break; case LibErrorCode::OperationNotSupported: code = Error::OperationNotSupported; break; case LibErrorCode::NoConnection: code = Error::NoConnection; break; case LibErrorCode::Network: code = Error::NetworkError; break; case LibErrorCode::Ssl: code = Error::SslError; break; case LibErrorCode::Runtime: code = Error::RuntimeError; break; case LibErrorCode::SessionCanceled: code = Error::SessionCanceled; break; case LibErrorCode::TimedOut: code = Error::TimedOut; break; case LibErrorCode::UserInteraction: code = Error::UserInteraction; break; case LibErrorCode::OperationFailed: code = Error::OperationFailed; break; case LibErrorCode::EncryptionFailure: code = Error::EncryptionFailed; break; case LibErrorCode::TOSNotAccepted: code = Error::TOSNotAccepted; break; case LibErrorCode::ForgotPassword: code = Error::ForgotPassword; break; case LibErrorCode::IncorrectDate: code = Error::IncorrectDate; break; default: code = Error::UnknownError; break; }; errMessage = message; } if (err > LibErrorCode::UserErr) { code = Error::UserDefinedError; errMessage = (QString::fromLatin1("%1:%2")).arg(err).arg(message); } Error error(code, errMessage); request.m_callback(QVariantMap(), error); } void SignonSessionCore::processStoreOperation(const StoreOperation &operation) { TRACE() << "Processing store operation."; CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); Q_ASSERT(db != 0); if (operation.m_storeType != StoreOperation::Blob) { if (!(db->updateCredentials(operation.m_info))) { BLAME() << "Error occurred while updating credentials."; } } else { TRACE() << "Processing --- StoreOperation::Blob"; if (!db->storeData(m_id, operation.m_authMethod, operation.m_blobData)) { BLAME() << "Error occurred while storing data."; } } } void SignonSessionCore::requestDone() { m_listOfRequests.removeFirst(); m_requestIsActive = false; QMetaObject::invokeMethod(this, "startNewRequest", Qt::QueuedConnection); } void SignonSessionCore::processResultReply(const QVariantMap &data) { TRACE(); keepInUse(); if (m_listOfRequests.isEmpty()) return; RequestData rd = m_listOfRequests.head(); if (!m_canceled) { QVariantMap filteredData = filterVariantMap(data); CredentialsAccessManager *camManager = CredentialsAccessManager::instance(); CredentialsDB *db = camManager->credentialsDB(); Q_ASSERT(db != 0); //update database entry if (m_id != SIGNOND_NEW_IDENTITY) { SignonIdentityInfo info = db->credentials(m_id); bool identityWasValidated = info.validated(); /* update username and password from ui interaction; do not allow * updating the username if the identity is validated */ if (!info.validated() && !m_tmpUsername.isEmpty()) { info.setUserName(m_tmpUsername); } if (!m_tmpPassword.isEmpty()) { info.setPassword(m_tmpPassword); } info.setValidated(true); StoreOperation storeOp(StoreOperation::Credentials); storeOp.m_info = info; processStoreOperation(storeOp); /* If the credentials are validated, the secrets db is not * available and not authorized keys are available, then * the store operation has been performed on the memory * cache only; inform the CAM about the situation. */ if (identityWasValidated && !db->isSecretsDBOpen()) { /* Send the storage not available event only if the curent * result processing is following a previous signon UI query. * This is to avoid unexpected UI pop-ups. */ if (m_queryCredsUiDisplayed) { SecureStorageEvent *event = new SecureStorageEvent( (QEvent::Type)SIGNON_SECURE_STORAGE_NOT_AVAILABLE); event->m_sender = static_cast(this); QCoreApplication::postEvent( CredentialsAccessManager::instance(), event, Qt::HighEventPriority); } } } m_tmpUsername.clear(); m_tmpPassword.clear(); //remove secret field from output if (m_method != QLatin1String("password") && filteredData.contains(SSO_KEY_PASSWORD)) filteredData.remove(SSO_KEY_PASSWORD); rd.m_callback(filteredData, Error::NoError); if (m_watcher && !m_watcher->isFinished()) { delete m_watcher; m_watcher = 0; } /* Inform SignOnUi that we are done */ if (m_queryCredsUiDisplayed) { m_signonui->cancelUiRequest(rd.m_cancelKey); m_queryCredsUiDisplayed = false; } } requestDone(); } void SignonSessionCore::processStore(const QVariantMap &data) { TRACE(); keepInUse(); if (m_id == SIGNOND_NEW_IDENTITY) { BLAME() << "Cannot store without identity"; return; } QVariantMap filteredData = data; //do not store username or password filteredData.remove(SSO_KEY_PASSWORD); filteredData.remove(SSO_KEY_USERNAME); filteredData.remove(SSO_ACCESS_CONTROL_TOKENS); //store data into db CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB(); Q_ASSERT(db != NULL); StoreOperation storeOp(StoreOperation::Blob); storeOp.m_blobData = filteredData; storeOp.m_authMethod = m_method; processStoreOperation(storeOp); /* If the credentials are validated, the secrets db is not available and * not authorized keys are available inform the CAM about the situation. */ SignonIdentityInfo info = db->credentials(m_id); if (info.validated() && !db->isSecretsDBOpen()) { /* Send the storage not available event only if the curent store * processing is following a previous signon UI query. This is to avoid * unexpected UI pop-ups. */ if (m_queryCredsUiDisplayed) { TRACE() << "Secure storage not available."; SecureStorageEvent *event = new SecureStorageEvent( (QEvent::Type)SIGNON_SECURE_STORAGE_NOT_AVAILABLE); event->m_sender = static_cast(this); QCoreApplication::postEvent( CredentialsAccessManager::instance(), event, Qt::HighEventPriority); } } m_queryCredsUiDisplayed = false; return; } void SignonSessionCore::processUiRequest(const QVariantMap &data) { TRACE(); keepInUse(); if (!m_canceled && !m_listOfRequests.isEmpty()) { RequestData &request = m_listOfRequests.head(); QString uiRequestId = request.m_cancelKey; if (m_watcher) { if (!m_watcher->isFinished()) m_signonui->cancelUiRequest(uiRequestId); delete m_watcher; m_watcher = 0; } request.m_params = filterVariantMap(data); request.m_params[SSOUI_KEY_REQUESTID] = uiRequestId; if (m_id == SIGNOND_NEW_IDENTITY) request.m_params[SSOUI_KEY_STORED_IDENTITY] = false; else request.m_params[SSOUI_KEY_STORED_IDENTITY] = true; request.m_params[SSOUI_KEY_IDENTITY] = m_id; request.m_params[SSOUI_KEY_CLIENT_DATA] = m_clientData; request.m_params[SSOUI_KEY_METHOD] = m_method; request.m_params[SSOUI_KEY_MECHANISM] = request.m_mechanism; /* Pass some data about the requesting client */ AccessControlManagerHelper *acm = AccessControlManagerHelper::instance(); request.m_params[SSOUI_KEY_PID] = acm->pidOfPeer(request.m_peerContext); request.m_params[SSOUI_KEY_APP_ID] = acm->appIdOfPeer(request.m_peerContext); CredentialsAccessManager *camManager = CredentialsAccessManager::instance(); CredentialsDB *db = camManager->credentialsDB(); Q_ASSERT(db != 0); //check that we have caption if (!data.contains(SSO_KEY_CAPTION)) { TRACE() << "Caption missing"; if (m_id != SIGNOND_NEW_IDENTITY) { SignonIdentityInfo info = db->credentials(m_id); request.m_params.insert(SSO_KEY_CAPTION, info.caption()); TRACE() << "Got caption: " << info.caption(); } } /* * Check the secure storage status, if any issues are encountered signal * this to the signon ui. */ if (!db->isSecretsDBOpen()) { TRACE(); //If there are no keys available if (!camManager->keysAvailable()) { TRACE() << "Secrets DB not available." << "CAM has no keys available. Informing signon-ui."; request.m_params[SSOUI_KEY_STORAGE_KEYS_UNAVAILABLE] = true; } } m_watcher = new QDBusPendingCallWatcher( m_signonui->queryDialog(request.m_params), this); m_queryCredsUiDisplayed = true; connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(queryUiSlot(QDBusPendingCallWatcher*))); } } void SignonSessionCore::processRefreshRequest(const QVariantMap &data) { TRACE(); keepInUse(); if (!m_canceled && !m_listOfRequests.isEmpty()) { QString uiRequestId = m_listOfRequests.head().m_cancelKey; if (m_watcher) { if (!m_watcher->isFinished()) m_signonui->cancelUiRequest(uiRequestId); delete m_watcher; m_watcher = 0; } m_listOfRequests.head().m_params = filterVariantMap(data); m_watcher = new QDBusPendingCallWatcher( m_signonui->refreshDialog(m_listOfRequests.head().m_params), this); m_queryCredsUiDisplayed = true; connect(m_watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(queryUiSlot(QDBusPendingCallWatcher*))); } } void SignonSessionCore::processError(int err, const QString &message) { TRACE(); keepInUse(); m_tmpUsername.clear(); m_tmpPassword.clear(); if (m_listOfRequests.isEmpty()) return; RequestData rd = m_listOfRequests.head(); if (!m_canceled) { replyError(rd, err, message); if (m_watcher && !m_watcher->isFinished()) { delete m_watcher; m_watcher = 0; } /* Inform SignOnUi that we are done */ if (m_queryCredsUiDisplayed) { m_queryCredsUiDisplayed = false; m_signonui->cancelUiRequest(rd.m_cancelKey); } } requestDone(); } void SignonSessionCore::stateChangedSlot(int state, const QString &message) { if (!m_canceled && !m_listOfRequests.isEmpty()) { RequestData rd = m_listOfRequests.head(); emit stateChanged(rd.m_cancelKey, (int)state, message); } keepInUse(); } void SignonSessionCore::childEvent(QChildEvent *ce) { if (ce->added()) keepInUse(); else if (ce->removed()) SignonDisposable::destroyUnused(); } void SignonSessionCore::customEvent(QEvent *event) { /* TODO: This method is useless now, and there's probably a simpler * way to handle the secure storage events than using QEvent (such * as direct signal connections). * For the time being, let this method live just for logging the * secure storage events. */ TRACE() << "Custom event received."; if (event->type() == SIGNON_SECURE_STORAGE_AVAILABLE) { TRACE() << "Secure storage is available."; } else if (event->type() == SIGNON_SECURE_STORAGE_NOT_AVAILABLE) { TRACE() << "Secure storage still not available."; } QObject::customEvent(event); } void SignonSessionCore::queryUiSlot(QDBusPendingCallWatcher *call) { keepInUse(); QDBusPendingReply reply = *call; bool isRequestToRefresh = false; Q_ASSERT_X(m_listOfRequests.size() != 0, __func__, "queue of requests is empty"); RequestData &rd = m_listOfRequests.head(); if (!reply.isError() && reply.count()) { QVariantMap resultParameters = reply.argumentAt<0>(); if (resultParameters.contains(SSOUI_KEY_REFRESH)) { isRequestToRefresh = true; resultParameters.remove(SSOUI_KEY_REFRESH); } rd.m_params = resultParameters; /* If the query ui was canceled or any other error occurred * we assume that the UI is not displayed. */ if (resultParameters.contains(SSOUI_KEY_ERROR) && (resultParameters[SSOUI_KEY_ERROR] == QUERY_ERROR_CANCELED)) { m_queryCredsUiDisplayed = false; } } else { rd.m_params.insert(SSOUI_KEY_ERROR, (int)SignOn::QUERY_ERROR_NO_SIGNONUI); m_queryCredsUiDisplayed = false; } if (!m_canceled) { /* Temporary caching, if credentials are valid * this data will be effectively cached */ m_tmpUsername = rd.m_params.value(SSO_KEY_USERNAME, QVariant()).toString(); m_tmpPassword = rd.m_params.value(SSO_KEY_PASSWORD, QVariant()).toString(); if (isRequestToRefresh) { TRACE() << "REFRESH IS REQUIRED"; rd.m_params.remove(SSOUI_KEY_REFRESH); m_plugin->processRefresh(rd.m_params); } else { m_plugin->processUi(rd.m_params); } } delete m_watcher; m_watcher = NULL; } void SignonSessionCore::startNewRequest() { keepInUse(); m_canceled = false; if (m_listOfRequests.isEmpty()) { TRACE() << "No more requests to process"; setAutoDestruct(true); return; } // there is an active request already if (m_requestIsActive) { TRACE() << "One request is already active"; return; } //there is some UI operation with plugin if (m_watcher && !m_watcher->isFinished()) { TRACE() << "Some UI operation is still pending"; return; } TRACE() << "Starting the authentication process"; setAutoDestruct(false); startProcess(); } void SignonSessionCore::destroy() { if (m_requestIsActive || m_watcher != NULL) { keepInUse(); return; } if (m_id) sessionsOfStoredCredentials.remove(sessionName(m_id, m_method)); else sessionsOfNonStoredCredentials.removeOne(this); QObjectList authSessions; while (authSessions = children(), !authSessions.isEmpty()) { delete authSessions.first(); } deleteLater(); } void SignonSessionCore::credentialsSystemReady() { QMetaObject::invokeMethod(this, "startNewRequest", Qt::QueuedConnection); } signond-nicolasfella/src/signond/signonsessioncoretools.cpp0000664000175000017500000000524614615454547024660 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2011 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signonsessioncoretools.h" #include #include "signond-common.h" using namespace SignonDaemonNS; QVariantMap SignonDaemonNS::mergeVariantMaps(const QVariantMap &map1, const QVariantMap &map2) { if (map1.isEmpty()) return map2; if (map2.isEmpty()) return map1; #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QVariantMap map = map1; //map2 values will overwrite map1 values for the same keys. QMapIterator it(map2); while (it.hasNext()) { it.next(); if (map.contains(it.key())) map.remove(it.key()); } return map.unite(map2); #else QVariantMap map = map1; map.insert(map2); return map; #endif } /* --------------------- StoreOperation ---------------------- */ StoreOperation::StoreOperation(const StoreType type): m_storeType(type) { } StoreOperation::StoreOperation(const StoreOperation &src): m_storeType(src.m_storeType), m_info(src.m_info), m_authMethod(src.m_authMethod), m_blobData(src.m_blobData) { } StoreOperation::~StoreOperation() { } /* --------------------- RequestData ---------------------- */ RequestData::RequestData(const PeerContext &peerContext, const QVariantMap ¶ms, const QString &mechanism, const QString &cancelKey, const ProcessCb &callback): m_peerContext(peerContext), m_callback(callback), m_params(params), m_mechanism(mechanism), m_cancelKey(cancelKey) { } RequestData::RequestData(const RequestData &other): m_peerContext(other.m_peerContext), m_callback(other.m_callback), m_params(other.m_params), m_mechanism(other.m_mechanism), m_cancelKey(other.m_cancelKey) { } RequestData::~RequestData() { } signond-nicolasfella/src/src.pro0000664000175000017500000000014514615454535017157 0ustar coucoufcoucoufTEMPLATE = subdirs SUBDIRS = \ signond \ plugins \ remotepluginprocess \ extensions signond-nicolasfella/tests/0000775000175000017500000000000014615454535016221 5ustar coucoufcoucoufsignond-nicolasfella/tests/com.google.code.AccountsSSO.SingleSignOn.service.in0000664000175000017500000000014414615454535027652 0ustar coucoufcoucouf[D-BUS Service] Name=com.google.code.AccountsSSO.SingleSignOn Exec=$${TOP_SRC_DIR}/tests/signond.sh signond-nicolasfella/tests/extensions/0000775000175000017500000000000014615454535020420 5ustar coucoufcoucoufsignond-nicolasfella/tests/extensions/extensions.pri0000664000175000017500000000046514615454535023340 0ustar coucoufcoucoufinclude(../tests.pri) QT += core \ sql \ testlib \ dbus QT -= gui LIBS += -lsignon-extension QMAKE_LIBDIR += \ $${TOP_BUILD_DIR}/lib/signond/SignOn QMAKE_RPATHDIR = $${QMAKE_LIBDIR} DEFINES += SIGNOND_TRACE DEFINES += SIGNON_PLUGIN_TRACE INCLUDEPATH += . \ $$TOP_SRC_DIR/lib/signond signond-nicolasfella/tests/extensions/extensions.pro0000664000175000017500000000010214615454535023332 0ustar coucoufcoucoufTEMPLATE = subdirs SUBDIRS = \ tst_access_control_manager.pro signond-nicolasfella/tests/extensions/tst_access_control_manager.cpp0000664000175000017500000000527214615454535026517 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include using namespace SignOn; class AccessControlManagerTest: public QObject { Q_OBJECT private Q_SLOTS: void test_abstract(); void test_abstractRequest(); }; void AccessControlManagerTest::test_abstract() { AbstractAccessControlManager *acm = new AbstractAccessControlManager(this); /* forge a QDBusMessage and a connection */ QDBusMessage msg = QDBusMessage::createMethodCall(":0.3", "/", "my.interface", "hi"); QDBusConnection conn(QLatin1String("test-connection")); QCOMPARE(acm->isPeerAllowedToAccess(conn, msg, QLatin1String("any")), true); QCOMPARE(acm->appIdOfPeer(conn, msg), QString()); QCOMPARE(acm->keychainWidgetAppId(), QString()); delete acm; } void AccessControlManagerTest::test_abstractRequest() { AbstractAccessControlManager *acm = new AbstractAccessControlManager(this); /* forge a QDBusMessage and a connection */ QDBusMessage msg = QDBusMessage::createMethodCall(":0.3", "/", "my.interface", "hi"); QDBusConnection conn(QLatin1String("test-connection")); AccessRequest request; request.setPeer(conn, msg); request.setIdentity(4); QCOMPARE(request.peerConnection().name(), conn.name()); QCOMPARE(request.peerMessage().member(), msg.member()); QCOMPARE(request.identity(), quint32(4)); AccessReply *reply = acm->handleRequest(request); QVERIFY(reply != 0); QVERIFY(!reply->isAccepted()); QSignalSpy finished(reply, SIGNAL(finished())); QTest::qWait(10); QCOMPARE(finished.count(), 1); QVERIFY(reply->isAccepted()); QCOMPARE(reply->request().identity(), request.identity()); delete reply; delete acm; } QTEST_MAIN(AccessControlManagerTest) #include "tst_access_control_manager.moc" signond-nicolasfella/tests/extensions/tst_access_control_manager.pro0000664000175000017500000000024614615454535026531 0ustar coucoufcoucoufinclude(extensions.pri) TARGET = tst_access_control_manager SOURCES += \ tst_access_control_manager.cpp check.depends = $$TARGET check.commands = "./$$TARGET" signond-nicolasfella/tests/libsignon-qt-tests/0000775000175000017500000000000014615454547021772 5ustar coucoufcoucoufsignond-nicolasfella/tests/libsignon-qt-tests/signon-ui.cpp0000664000175000017500000000602014615454535024401 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signon-ui.h" #include "SignOn/uisessiondata.h" #include "SignOn/uisessiondata_priv.h" #include #include #include static const char serviceName[] = "com.nokia.singlesignonui"; static const char objectPath[] = "/SignonUi"; SignOnUI::SignOnUI(QDBusConnection connection, QObject *parent): QObject(parent), QDBusContext(), m_connection(connection), m_replyPassword("SSOUI default password"), m_delay(0) { connection.registerObject(QLatin1String(objectPath), this, QDBusConnection::ExportAllContents); connection.registerService(QLatin1String(serviceName)); } SignOnUI::~SignOnUI() { m_connection.unregisterService(QLatin1String(serviceName)); m_connection.unregisterObject(QLatin1String(objectPath)); } QVariantMap SignOnUI::clientData() const { if (!m_parameters.contains(SSOUI_KEY_CLIENT_DATA)) { return QVariantMap(); } QVariant variant = m_parameters[SSOUI_KEY_CLIENT_DATA]; return (variant.type() == QVariant::Map) ? variant.toMap() : qdbus_cast(variant.value()); } QString SignOnUI::method() const { return m_parameters.value(SSOUI_KEY_METHOD).toString(); } QString SignOnUI::mechanism() const { return m_parameters.value(SSOUI_KEY_MECHANISM).toString(); } void SignOnUI::cancelUiRequest(const QString &requestId) { qDebug() << Q_FUNC_INFO << requestId; } QVariantMap SignOnUI::queryDialog(const QVariantMap ¶meters) { qDebug() << Q_FUNC_INFO << parameters; m_parameters = parameters; QVariantMap result = parameters; if (parameters.value(SSOUI_KEY_QUERYPASSWORD, false).toBool()) { result.remove(SSOUI_KEY_QUERYPASSWORD); result.insert(SSOUI_KEY_PASSWORD, m_replyPassword); } result.insert(SSOUI_KEY_ERROR, SignOn::QUERY_ERROR_NONE); m_reply = message().createReply(result); setDelayedReply(true); QTimer::singleShot(m_delay, this, SLOT(processQueryDialog())); return QVariantMap(); } QVariantMap SignOnUI::refreshDialog(const QVariantMap ¶meters) { qDebug() << Q_FUNC_INFO << parameters; return parameters; } void SignOnUI::processQueryDialog() { m_connection.send(m_reply); } signond-nicolasfella/tests/libsignon-qt-tests/signon-ui.h0000664000175000017500000000463714615454535024062 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_UI_H #define SIGNON_UI_H #include "SignOn/signonerror.h" #include #include #include #include #include class SignOnUI: public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "com.nokia.singlesignonui") public: SignOnUI(QDBusConnection connection, QObject *parent = 0); ~SignOnUI(); /*! * Add an artificial delay to the queryDialog() replies. */ void setDelay(int seconds) { m_delay = seconds * 1000; } /*! * Get the parameters sent with the last request. */ QVariantMap parameters() const { return m_parameters; } /*! * Get the client data. */ QVariantMap clientData() const; /*! * Get the authentication method. */ QString method() const; /*! * Get the authentication mechanism. */ QString mechanism() const; /*! * Set the password which will be returned to the next query. */ void setPassword(const QString &password) { m_replyPassword = password; } /*! * Get the password used by SignOnUI. */ QString password() const { return m_replyPassword; } public Q_SLOTS: Q_NOREPLY void cancelUiRequest(const QString &requestId); QVariantMap queryDialog(const QVariantMap ¶meters); QVariantMap refreshDialog(const QVariantMap &newParameters); private Q_SLOTS: void processQueryDialog(); private: QDBusMessage m_reply; QDBusConnection m_connection; QVariantMap m_parameters; QString m_replyPassword; int m_delay; }; #endif // SIGNON_UI_H signond-nicolasfella/tests/libsignon-qt-tests/ssotestclient.cpp0000664000175000017500000015665214615454535025415 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "SignOn/uisessiondata.h" #include "SignOn/uisessiondata_priv.h" #include "signon-ui.h" #include "ssotestclient.h" #include #include #include #include #include using namespace SignOn; int startedClients = 0; int finishedClients = 0; /* * test timeout 10 seconds * */ #define test_timeout 10000 #define pause_time 0 #define TEST_START qDebug("\n\n\n\n ----------------- %s ----------------\n\n", __func__); #define TEST_DONE qDebug("\n\n ----------------- %s PASS ----------------\n\n", __func__); // ACL Tokens for the queryAuthPluginACL test #define ACL_TOKEN_0 "token_0" #define ACL_TOKEN_1 "token_1" #define ACL_TOKEN_2 "libsignon-qt-tests::sso-encryption-token" #define ACL_TOKEN_3 "token_3" #define ACL_TOKEN_4 "token_4" #define ACL_TOKEN_5 "AID::com.nokia.maemo.libsignon-qt-tests.libsignon-qt-tests-id" SsoTestClient::SsoTestClient(SignOnUI *signOnUI, QObject *parent): QObject(parent), m_signOnUI(signOnUI) { } void SsoTestClient::initTestCase() { clearDB(); initAuthServiceTest(); } void SsoTestClient::cleanupTestCase() { clearDB(); } QString SsoTestClient::errCodeAsStr(const Error::ErrorType err) { switch(err) { case Error::Unknown: return "Unknown"; case Error::InternalServer: return "InternalServer"; case Error::InternalCommunication: return "InternalCommunication"; case Error::PermissionDenied: return "PermissionDenied"; case Error::MethodNotKnown: return "MethodNotKnown"; case Error::ServiceNotAvailable: return "ServiceNotAvailable"; case Error::InvalidQuery: return "InvalidQuery"; case Error::MethodNotAvailable: return "MethodNotAvailable"; case Error::IdentityNotFound: return "IdentityNotFound"; case Error::StoreFailed: return "StoreFailed"; case Error::RemoveFailed: return "RemoveFailed"; case Error::SignOutFailed: return "SignOutFailed"; case Error::IdentityOperationCanceled: return "IdentityOperationCanceled"; case Error::CredentialsNotAvailable: return "CredentialsNotAvailable"; case Error::AuthSessionErr: return "AuthSessionErr"; case Error::MechanismNotAvailable: return "MechanismNotAvailable"; case Error::MissingData: return "MissingData"; case Error::InvalidCredentials: return "InvalidCredentials"; case Error::WrongState: return "WrongState"; case Error::OperationNotSupported: return "OperationNotSupported"; case Error::NoConnection: return "NoConnection"; case Error::Network: return "Network"; case Error::Ssl: return "Ssl"; case Error::Runtime: return "Runtime"; case Error::SessionCanceled: return "SessionCanceled"; case Error::TimedOut: return "TimedOut"; case Error::UserInteraction: return "UserInteraction"; case Error::OperationFailed: return "OperationFailed"; default: return "DEFAULT error type reached."; } } bool SsoTestClient::storeCredentialsPrivate(const SignOn::IdentityInfo &info) { Identity *identity = Identity::newIdentity(info, this); QEventLoop loop; connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(identity, SIGNAL(credentialsStored(const quint32)), &m_identityResult, SLOT(credentialsStored(const quint32))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->storeCredentials(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); bool ok = false; if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { m_storedIdentityInfo = info; m_storedIdentityId = identity->id(); ok = true; } else { qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << errCodeAsStr(m_identityResult.m_error); ok = false; } delete identity; return ok; } QString SsoTestClient::pluginsDir() const { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); if (env.contains(QLatin1String("SSO_PLUGINS_DIR"))) { return env.value(QLatin1String("SSO_PLUGINS_DIR")); } else { return QLatin1String(SIGNOND_PLUGINS_DIR); } } void SsoTestClient::queryAvailableMetods() { TEST_START //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for querying available methods."); Identity *identity = Identity::existingIdentity(m_storedIdentityId, this); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); m_identityResult.reset(); QEventLoop loop; connect(identity, SIGNAL(methodsAvailable(const QStringList &)), &m_identityResult, SLOT(methodsAvailable(const QStringList &))); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->queryAvailableMethods(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { qDebug() << "Remote:" << m_identityResult.m_methods; qDebug() << "Local:" << m_storedIdentityInfo.methods(); QVERIFY(m_identityResult.m_methods == m_storedIdentityInfo.methods()); } else { qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << errCodeAsStr(m_identityResult.m_error); QVERIFY(false); } TEST_DONE } void SsoTestClient::requestCredentialsUpdate() { TEST_START m_signOnUI->setPassword("Hello there, this is my password"); Identity *identity = Identity::existingIdentity(m_storedIdentityId, this); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); m_identityResult.reset(); QEventLoop loop; connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(identity, SIGNAL(credentialsStored(const quint32)), &m_identityResult, SLOT(credentialsStored(const quint32))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->requestCredentialsUpdate(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); qDebug() << m_signOnUI->parameters(); QVERIFY(m_identityResult.m_responseReceived == TestIdentityResult::NormalResp); /* Verify that the password is the one set by signon UI */ connect(identity, SIGNAL(secretVerified(const bool)), &m_identityResult, SLOT(secretVerified(const bool))); identity->verifySecret(m_signOnUI->password()); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QCOMPARE(m_identityResult.m_responseReceived, TestIdentityResult::NormalResp); QVERIFY(m_identityResult.m_secretVerified); TEST_DONE } void SsoTestClient::storeCredentials_data() { QTest::addColumn("addMethods"); QTest::newRow("with methods") << true; QTest::newRow("without methods") << false; } void SsoTestClient::storeCredentials() { TEST_START QFETCH(bool, addMethods); m_identityResult.reset(); QMap methods; if (addMethods) { methods.insert("dummy", QStringList() << "mech1" << "mech2" << "mech3"); methods.insert("dummy1", QStringList() << "mech11" << "mech12" << "mech13"); } IdentityInfo info("TEST_CAPTION", "TEST_USERNAME", methods); info.setSecret("TEST_SECRET"); info.setRealms(QStringList() << "TEST_REALM1" << "TEST_REALM2"); info.setAccessControlList(QStringList() << "*"); Identity *identity = Identity::newIdentity(info, this); QEventLoop loop; connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(identity, SIGNAL(credentialsStored(const quint32)), &m_identityResult, SLOT(credentialsStored(const quint32))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()), Qt::QueuedConnection); identity->storeCredentials(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); if (m_identityResult.m_responseReceived == TestIdentityResult::InexistentResp) { QFAIL("A response was not received."); } if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QCOMPARE(m_identityResult.m_id, identity->id()); Identity *existingIdentity = Identity::existingIdentity(m_identityResult.m_id, this); QVERIFY2(existingIdentity != NULL, "Could not create existing identity. '0' ID provided?"); connect(existingIdentity, SIGNAL(info(const SignOn::IdentityInfo &)), &m_identityResult, SLOT(info(const SignOn::IdentityInfo &))); existingIdentity->queryInfo(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); delete existingIdentity; if (!TestIdentityResult::compareIdentityInfos(m_identityResult.m_idInfo, info)) { QFAIL("Compared identity infos are not the same."); } } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_serviceResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Error received"); } // Test update credentials functionality Identity *existingIdentity = Identity::existingIdentity(m_identityResult.m_id, this); QVERIFY2(existingIdentity != NULL, "Could not create existing identity. '0' ID provided?"); methods.clear(); if (addMethods) { methods.insert("dummy1", QStringList() << "mech11" << "mech12" << "mech13"); methods.insert("dummy2", QStringList() << "mech1_updated" << "mech2" << "mech1_updated2"); methods.insert("dummy3", QStringList() << "mech1_updated" << "mech2" << "mech1_updated2"); } IdentityInfo updateInfo("TEST_CAPTION", "TEST_USERNAME_UPDATED", methods); updateInfo.setSecret("TEST_SECRET_YES", false); do { QEventLoop loop; connect(existingIdentity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(existingIdentity, SIGNAL(credentialsStored(const quint32)), &m_identityResult, SLOT(credentialsStored(const quint32))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()), Qt::QueuedConnection); existingIdentity->storeCredentials(updateInfo); qDebug(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); } while(0); if (m_identityResult.m_responseReceived == TestIdentityResult::InexistentResp) { QFAIL("A response was not received."); } if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QEventLoop loop; connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()), Qt::QueuedConnection); connect(existingIdentity, SIGNAL(info(const SignOn::IdentityInfo &)), &m_identityResult, SLOT(info(const SignOn::IdentityInfo &))); existingIdentity->queryInfo(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); qDebug() << "ID:" << existingIdentity->id(); QCOMPARE(m_identityResult.m_idInfo.caption(), updateInfo.caption()); QCOMPARE(m_identityResult.m_idInfo.methods(), updateInfo.methods()); QCOMPARE(m_identityResult.m_idInfo.userName(), updateInfo.userName()); } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_serviceResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Error received"); } TEST_DONE } void SsoTestClient::remove() { QSKIP("Skipping until secure storage gets stabilized.", SkipSingle); TEST_START m_identityResult.reset(); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for removing identity."); Identity *identity = Identity::existingIdentity(m_storedIdentityId, this); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); QEventLoop loop; connect(identity, SIGNAL(removed()), &m_identityResult, SLOT(removed())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->remove(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QVERIFY(m_identityResult.m_removed); connect( identity, SIGNAL(info(const SignOn::IdentityInfo &)), &m_identityResult, SLOT(info(const SignOn::IdentityInfo &))); qDebug() << "Going to query info"; identity->queryInfo(); QVERIFY(m_identityResult.m_responseReceived == TestIdentityResult::ErrorResp); QVERIFY(m_identityResult.m_error == Error::IdentityNotFound); } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } TEST_DONE } void SsoTestClient::sessionTest() { TEST_START Identity *id = Identity::newIdentity(); QLatin1String method1Str("mtd1"); AuthSessionP session1 = id->createSession(method1Str); QVERIFY2(session1 != 0, "Could not create auth session."); AuthSessionP session2 = id->createSession(method1Str); QVERIFY2(session2 == 0, "Multiple auth. sessions with same method created."); AuthSessionP session3 = id->createSession("method2"); QVERIFY2(session3 != 0, "Could not create auth session."); id->destroySession(session1); session2 = id->createSession(method1Str); AuthSessionP session5 = NULL; id->destroySession(session5); delete id; TEST_DONE } void SsoTestClient::removeStoreRemove() { QSKIP("Skipping until secure storage gets stabilized.", SkipSingle); TEST_START m_identityResult.reset(); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for removing identity."); Identity *identity = Identity::existingIdentity(m_storedIdentityId, this); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); QEventLoop loop; connect( identity, SIGNAL(removed()), &m_identityResult, SLOT(removed())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); m_identityResult.reset(); identity->remove(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QVERIFY(m_identityResult.m_removed); m_identityResult.reset(); qDebug() << "Checking for removed identity ID : " << identity->id();; connect(identity, SIGNAL(credentialsStored(const quint32)), &m_identityResult, SLOT(credentialsStored(const quint32))); QMap methods; methods.insert("method4", QStringList() << "mech10" << "mech20"); methods.insert("method5", QStringList() << "mech10" << "mech20" << "mech30"); IdentityInfo updateInfo("TEST_CAPTION_10", "TEST_USERNAME_10", methods); updateInfo.setSecret("TEST_PASSWORD_10"); updateInfo.setAccessControlList(QStringList() << "*"); m_identityResult.m_responseReceived = TestIdentityResult::InexistentResp; identity->storeCredentials(updateInfo); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { m_storedIdentityInfo = info; m_storedIdentityId = identity->id(); qDebug() << "Identity ID = " << m_storedIdentityId; } else { qDebug() << "Error reply: " << m_identityResult.m_errMsg << "." "\nError code: " << errCodeAsStr(m_identityResult.m_error); QFAIL("Failed to store the credentials"); } connect( identity, SIGNAL(info(const SignOn::IdentityInfo &)), &m_identityResult, SLOT(info(const SignOn::IdentityInfo &))); qDebug() << "Checking if the identity info is updated in identity"; m_identityResult.reset(); identity->queryInfo(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY(m_identityResult.m_responseReceived == TestIdentityResult::NormalResp); if (!TestIdentityResult::compareIdentityInfos(m_identityResult.m_idInfo, updateInfo)) { QFAIL("Compared identity infos are not the same."); } qDebug() << "Removing after store"; m_identityResult.reset(); identity->remove(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); QVERIFY(m_identityResult.m_removed); qDebug() << "Removing again"; m_identityResult.reset(); identity->remove(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY(m_identityResult.m_responseReceived == TestIdentityResult::ErrorResp); QVERIFY(m_identityResult.m_error == Error::IdentityNotFound); } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } delete identity; TEST_DONE } void SsoTestClient::multipleRemove() { QSKIP("Skipping until secure storage gets stabilized.", SkipSingle); TEST_START m_identityResult.reset(); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for removing identity."); Identity *identity = Identity::existingIdentity(m_storedIdentityId, this); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); QEventLoop loop; connect( identity, SIGNAL(removed()), &m_identityResult, SLOT(removed())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->remove(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QVERIFY(m_identityResult.m_removed); qDebug() << "Removing again"; m_identityResult.reset(); identity->remove(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY(m_identityResult.m_responseReceived == TestIdentityResult::ErrorResp); QVERIFY(m_identityResult.m_error == Error::IdentityNotFound); } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } delete identity; TEST_DONE } void SsoTestClient::queryInfo() { TEST_START m_identityResult.reset(); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setRealms(QStringList() << "test_realm"); QStringList acl; acl << "*"; info.setAccessControlList(acl); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for querying info."); Identity *identity = Identity::existingIdentity(m_storedIdentityId); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); QEventLoop loop; connect( identity, SIGNAL(info(const SignOn::IdentityInfo &)), &m_identityResult, SLOT(info(const SignOn::IdentityInfo &))); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->queryInfo(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); QCOMPARE(m_identityResult.m_idInfo.isStoringSecret(), true); QCOMPARE(m_identityResult.m_idInfo.accessControlList(), acl); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QVERIFY(m_identityResult.m_id == m_storedIdentityId); QVERIFY(TestIdentityResult::compareIdentityInfos( m_storedIdentityInfo, m_identityResult.m_idInfo, false)); } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received an error reply."); } TEST_DONE } void SsoTestClient::addReference() { TEST_START m_identityResult.reset(); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setRealms(QStringList() << "test_realm"); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for querying info."); Identity *identity = Identity::existingIdentity(m_storedIdentityId); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); m_identityResult.m_removed = false; QEventLoop loop; connect( identity, SIGNAL(referenceAdded()), &m_identityResult, SLOT(referenceAdded())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->addReference(QLatin1String("testref")); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QVERIFY(m_identityResult.m_removed); } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received an error reply."); } TEST_DONE } void SsoTestClient::removeReference() { m_identityResult.reset(); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setRealms(QStringList() << "test_realm"); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for querying info."); Identity *identity = Identity::existingIdentity(m_storedIdentityId); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); m_identityResult.m_removed = false; QEventLoop loop; identity->addReference(QLatin1String("testref")); connect( identity, SIGNAL(referenceRemoved()), &m_identityResult, SLOT(referenceRemoved())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->removeReference(QLatin1String("testref")); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QVERIFY(m_identityResult.m_removed); } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received an error reply."); } TEST_DONE } void SsoTestClient::verifyUser() { TEST_START m_identityResult.reset(); const QString password(QLatin1String("A strong password")); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret(password); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for verifying user."); Identity *identity = Identity::existingIdentity(m_storedIdentityId); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); QEventLoop loop; connect( identity, SIGNAL(userVerified(const bool)), &m_identityResult, SLOT(userVerified(const bool))); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); m_signOnUI->setPassword(password); identity->verifyUser("message"); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); QVERIFY(m_identityResult.m_responseReceived == TestIdentityResult::NormalResp); /* check that the parameters received by SignOnUI were correct */ QVariantMap uiParameters = m_signOnUI->parameters(); QCOMPARE(uiParameters.value(SSOUI_KEY_MESSAGE).toString(), QLatin1String("message")); QVERIFY(uiParameters.contains(SSOUI_KEY_QUERYPASSWORD)); /* check that the verification was successful */ QVERIFY(m_identityResult.m_userVerified); TEST_DONE } void SsoTestClient::verifySecret() { TEST_START m_identityResult.reset(); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for verifying secret."); Identity *identity = Identity::existingIdentity(m_storedIdentityId); if (identity == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); QEventLoop loop; connect( identity, SIGNAL(secretVerified(const bool)), &m_identityResult, SLOT(secretVerified(const bool))); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->verifySecret("TEST_PASSWORD_1"); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) { QVERIFY(m_identityResult.m_secretVerified); } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received an error reply."); } TEST_DONE } void SsoTestClient::signOut() { TEST_START m_identityResult.reset(); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret("TEST_PASSWORD_1"); info.setAccessControlList(QStringList() << "*"); if (!storeCredentialsPrivate(info)) QFAIL("Failed to initialize test for signing out."); //create the existing identities Identity *identity = Identity::existingIdentity(m_storedIdentityId); Identity *identity1 = Identity::existingIdentity(m_storedIdentityId); Identity *identity2 = Identity::existingIdentity(m_storedIdentityId); Identity *identity3 = Identity::existingIdentity(m_storedIdentityId); if (identity == NULL || identity1 == NULL || identity2 == NULL || identity3 == NULL) QFAIL("Could not create existing identity. '0' ID provided?"); connect( identity, SIGNAL(signedOut()), &m_identityResult, SLOT(signedOut())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); //connect the other 2 identities to designated identity test result objects TestIdentityResult identityResult1; TestIdentityResult identityResult2; TestIdentityResult identityResult3; connect( identity1, SIGNAL(signedOut()), &identityResult1, SLOT(signedOut())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect( identity2, SIGNAL(signedOut()), &identityResult2, SLOT(signedOut())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect( identity3, SIGNAL(signedOut()), &identityResult3, SLOT(signedOut())); connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); /* Interesting - NOT IN THE GOOD WAY !!! - this wait has to be added so that the last identity gets to be registered and so that the server can signal it to sign out, too, @TODO */ QTest::qWait(100); identity->signOut(); //this test is likelly to take longer QTest::qWait(2000); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); QVERIFY2(identityResult1.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); QVERIFY2(identityResult2.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); QVERIFY2(identityResult3.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); if ((m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) && (identityResult1.m_responseReceived == TestIdentityResult::NormalResp) && (identityResult2.m_responseReceived == TestIdentityResult::NormalResp) && (identityResult3.m_responseReceived == TestIdentityResult::NormalResp)) { // probably will do something here in the future } else { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } TEST_DONE } void SsoTestClient::clearDB() { AuthService *service = new AuthService(this); QEventLoop loop; connect(service, SIGNAL(cleared()), &m_serviceResult, SLOT(cleared())); connect(service, SIGNAL(error(const SignOn::Error &)), &m_serviceResult, SLOT(error(const SignOn::Error &))); connect(&m_serviceResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); service->clear(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); } void SsoTestClient::initAuthServiceTest() { //small params preparing m_numberOfInsertedCredentials = 5; m_expectedNumberOfMethods = (QDir(pluginsDir())).entryList( QStringList() << "*.so", QDir::Files).count(); if (!m_expectedMechanisms.length()) m_expectedMechanisms << "mech1" << "mech2" << "mech3" << "BLOB"; m_methodToQueryMechanisms = "ssotest"; #ifdef SSO_TESTS_RUNNING_AS_UNTRUSTED return; #endif /* clearing DB * This may fail if the CAM is not ready; since the CAM state is not * exposed in the client API, in case we get the InternalServer error * (which is emitted in these cases) we wait some time and we retry. */ int retries = 0; do { clearDB(); if (m_serviceResult.m_responseReceived != TestAuthServiceResult::ErrorResp) break; if (m_serviceResult.m_error != Error::InternalServer) break; QTest::qSleep(2000); retries++; } while (retries < 5); if (m_serviceResult.m_responseReceived != TestAuthServiceResult::NormalResp) { /* DB clearing can fail - if the secrets DB is not available. * Do not fail in general if the clearing of the DB reported an error; * just print the debug output. */ QString codeStr = errCodeAsStr(m_serviceResult.m_error); qDebug() << "Error reply: " << m_serviceResult.m_errMsg << ".\nError code: " << codeStr; } //inserting some credentials for(int i = 0; i < m_numberOfInsertedCredentials; i++) { QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info(QString("TEST_CAPTION_%1").arg(i), QString("TEST_USERNAME_%1").arg(i), methods); info.setSecret(QString("TEST_PASSWORD_%1").arg(i)); Identity *identity = Identity::newIdentity(info); QEventLoop loop; connect(identity, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(identity, SIGNAL(credentialsStored(const quint32)), &m_identityResult, SLOT(credentialsStored(const quint32))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); identity->storeCredentials(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); if (m_identityResult.m_responseReceived != TestIdentityResult::NormalResp) { QString codeStr = errCodeAsStr(m_identityResult.m_error); qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Failed to prepare the AuthService test suite."); } delete identity; } } void SsoTestClient::queryMethods() { TEST_START m_serviceResult.reset(); AuthService service; QEventLoop loop; connect( &service, SIGNAL(methodsAvailable(const QStringList &)), &m_serviceResult, SLOT(methodsAvailable(const QStringList &))); connect(&service, SIGNAL(error(const SignOn::Error &)), &m_serviceResult, SLOT(error(const SignOn::Error &))); connect(&m_serviceResult, SIGNAL(testCompleted()), &loop, SLOT(quit()), Qt::QueuedConnection); service.queryMethods(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_serviceResult.m_responseReceived != TestAuthServiceResult::InexistentResp, "A response was not received."); if (m_serviceResult.m_responseReceived == TestAuthServiceResult::NormalResp) { //this should compare the actual lists not only their count QCOMPARE(m_serviceResult.m_methods.count(), m_expectedNumberOfMethods); } else { QString codeStr = errCodeAsStr(m_serviceResult.m_error); qDebug() << "Error reply: " << m_serviceResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } TEST_DONE } void SsoTestClient::queryMechanisms() { TEST_START m_serviceResult.reset(); AuthService service; QEventLoop loop; connect( &service, SIGNAL(mechanismsAvailable(const QString &, const QStringList &)), &m_serviceResult, SLOT(mechanismsAvailable(const QString &, const QStringList &))); connect(&service, SIGNAL(error(const SignOn::Error &)), &m_serviceResult, SLOT(error(const SignOn::Error &))); connect(&m_serviceResult, SIGNAL(testCompleted()), &loop, SLOT(quit()), Qt::QueuedConnection); service.queryMechanisms(m_methodToQueryMechanisms); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_serviceResult.m_responseReceived != TestAuthServiceResult::InexistentResp, "A response was not received."); if (m_serviceResult.m_responseReceived == TestAuthServiceResult::NormalResp) { qDebug() << m_serviceResult.m_queriedMechsMethod; qDebug() << m_methodToQueryMechanisms; qDebug() << m_serviceResult.m_mechanisms.second; qDebug() << m_expectedMechanisms; QCOMPARE(m_serviceResult.m_queriedMechsMethod, m_methodToQueryMechanisms); bool equal = (m_serviceResult.m_mechanisms.second == m_expectedMechanisms); QVERIFY(equal); } else { QString codeStr = errCodeAsStr(m_serviceResult.m_error); qDebug() << "Error reply: " << m_serviceResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } TEST_DONE } void SsoTestClient::queryIdentities() { TEST_START m_serviceResult.reset(); AuthService service; QEventLoop loop; connect(&service, SIGNAL(identities(const QList &)), &m_serviceResult, SLOT(identities(const QList &))); connect(&service, SIGNAL(error(const SignOn::Error &)), &m_serviceResult, SLOT(error(const SignOn::Error &))); connect(&m_serviceResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); service.queryIdentities(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_serviceResult.m_responseReceived != TestAuthServiceResult::InexistentResp, "A response was not received."); if (m_serviceResult.m_responseReceived == TestAuthServiceResult::NormalResp) { QListIterator it(m_serviceResult.m_identities); while (it.hasNext()) { IdentityInfo info = it.next(); qDebug() << "Identity record: " << "id:" << info.id() << " username: " << info.userName() << " caption: " << info.caption() << " methods:"; foreach(QString method, info.methods()) qDebug() << QPair(method, info.mechanisms(method)); } QCOMPARE(m_serviceResult.m_identities.count(), m_numberOfInsertedCredentials); } else { QString codeStr = errCodeAsStr(m_serviceResult.m_error); qDebug() << "Error reply: " << m_serviceResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } TEST_DONE } void SsoTestClient::queryIdentitiesWithFilter() { QSKIP("Test requires the implementation of the filtering feature.", SkipSingle); TEST_START m_serviceResult.reset(); int filteredIdentitiesCount = 2; IdentityInfo info(QLatin1String("CAPTION"), QLatin1String("TEST_FILTER_USERNAME"), QMap()); QVERIFY(storeCredentialsPrivate(info)); info.setRealms(QStringList() << QLatin1String("www.realm-filter.com")); QVERIFY(storeCredentialsPrivate(info)); AuthService service; QEventLoop loop; connect(&service, SIGNAL(identities(const QList &)), &m_serviceResult, SLOT(identities(const QList &))); connect(&service, SIGNAL(error(const SignOn::Error &)), &m_serviceResult, SLOT(error(const SignOn::Error &))); connect(&m_serviceResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); QString userPattern = QString::fromLatin1("TEST_FILTER"); QString realmPattern = QString::fromLatin1("*realm_filter*"); AuthService::IdentityRegExp userRegexp(userPattern); AuthService::IdentityRegExp realmRegexp(realmPattern); QVERIFY(userPattern == userRegexp.pattern()); QVERIFY(realmPattern == realmRegexp.pattern()); QString patternCopy = realmRegexp.pattern(); AuthService::IdentityFilter filter; filter.insert(AuthService::Username, userRegexp); filter.insert(AuthService::Realm, realmRegexp); service.queryIdentities(filter); service.queryIdentities(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_serviceResult.m_responseReceived != TestAuthServiceResult::InexistentResp, "A response was not received."); if (m_serviceResult.m_responseReceived == TestAuthServiceResult::NormalResp) { QListIterator it(m_serviceResult.m_identities); while(it.hasNext()) { IdentityInfo info = it.next(); qDebug() << "Identity record: " << "id:" << info.id() << " username: " << info.userName() << " caption: " << info.caption() << " methods:"; foreach (QString method, info.methods()) qDebug() << QPair(method, info.mechanisms(method)); } QCOMPARE(m_serviceResult.m_identities.count(), filteredIdentitiesCount); } else { QString codeStr = errCodeAsStr(m_serviceResult.m_error); qDebug() << "Error reply: " << m_serviceResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } TEST_DONE } void SsoTestClient::queryAuthPluginACL() { TEST_START QEventLoop loop; //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); methods.insert("ssotest", QStringList() << "mech1"); IdentityInfo info("test_caption_1", "test_username_1", methods); info.setSecret("test_password_1"); info.setAccessControlList(QStringList() << ACL_TOKEN_0 << ACL_TOKEN_1 << ACL_TOKEN_2 << ACL_TOKEN_3 << ACL_TOKEN_4 << ACL_TOKEN_5); Identity *id = Identity::newIdentity(info, this); connect(id, SIGNAL(credentialsStored(quint32)), &m_identityResult, SLOT(credentialsStored(quint32))); connect(id, SIGNAL(error(const SignOn::Error &)), &m_identityResult, SLOT(error(const SignOn::Error &))); connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); id->storeCredentials(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); if (m_identityResult.m_responseReceived != TestIdentityResult::NormalResp) { qDebug() << "Error reply: " << m_identityResult.m_errMsg << ".\nError code: " << errCodeAsStr(m_identityResult.m_error); QFAIL("Store identity failed."); } AuthSession *as = id->createSession(QLatin1String("ssotest")); connect(as, SIGNAL(response(const SignOn::SessionData &)), this, SLOT(response(const SignOn::SessionData &))); QSignalSpy errorSpy(as, SIGNAL(error(const SignOn::Error &))); QSignalSpy responseSpy(as, SIGNAL(response(const SignOn::SessionData &))); QObject::connect(as, SIGNAL(response(const SignOn::SessionData &)), &loop, SLOT(quit()), Qt::QueuedConnection); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); if (!errorSpy.count()) loop.exec(); QVERIFY(errorSpy.count() == 0); QVERIFY(responseSpy.count() == 1); QCOMPARE(m_tokenList.count(), 6); QVERIFY(m_tokenList.contains(ACL_TOKEN_5)); TEST_DONE } void SsoTestClient::response(const SignOn::SessionData &data) { m_tokenList = data.getAccessControlTokens(); } void SsoTestClient::clear() { QSKIP("Skipping until secure storage gets stabilized.", SkipSingle); TEST_START m_serviceResult.reset(); AuthService service; QEventLoop loop; connect( &service, SIGNAL(cleared()), &m_serviceResult, SLOT(cleared())); connect(&service, SIGNAL(error(const SignOn::Error &)), &m_serviceResult, SLOT(error(const SignOn::Error &))); connect(&m_serviceResult, SIGNAL(testCompleted()), &loop, SLOT(quit())); service.clear(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_serviceResult.m_responseReceived != TestAuthServiceResult::InexistentResp, "A response was not received."); if (m_serviceResult.m_responseReceived == TestAuthServiceResult::NormalResp) { connect( &service, SIGNAL(identities(const QList &)), &m_serviceResult, SLOT(identities(const QList &))); service.queryIdentities(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY(m_serviceResult.m_identities.count() == 0); } else { QString codeStr = errCodeAsStr(m_serviceResult.m_error); qDebug() << "Error reply: " << m_serviceResult.m_errMsg << ".\nError code: " << codeStr; QFAIL("Should not have received error reply"); } TEST_DONE } void SsoTestClient::emptyPasswordRegression() { TEST_START m_identityResult.reset(); QString myPassword("My password"); //inserting some credentials QMap methods; methods.insert("method1", QStringList() << "mech1" << "mech2"); methods.insert("method2", QStringList() << "mech1" << "mech2" << "mech3"); IdentityInfo info("TEST_CAPTION_1", "TEST_USERNAME_1", methods); info.setSecret(myPassword); info.setRealms(QStringList() << "test_realm"); QStringList acl; acl << "*"; info.setAccessControlList(acl); Identity *identity = Identity::newIdentity(info); QEventLoop loop; const char *errorSignature = SIGNAL(error(const SignOn::Error &)); QSignalSpy errorSignal(identity, errorSignature); connect(identity, errorSignature, &loop, SLOT(quit())); const char *credentialsStoredSignature = SIGNAL(credentialsStored(const quint32)); QSignalSpy credentialsStoredSignal(identity, credentialsStoredSignature); connect(identity, credentialsStoredSignature, &loop, SLOT(quit())); identity->storeCredentials(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QCOMPARE(errorSignal.count(), 0); QCOMPARE(credentialsStoredSignal.count(), 1); credentialsStoredSignal.clear(); /* Verify that the password is the one set by signon UI */ const char *secretVerifiedSignature = SIGNAL(secretVerified(const bool)); QSignalSpy secretVerifiedSignal(identity, secretVerifiedSignature); connect(identity, secretVerifiedSignature, &loop, SLOT(quit())); identity->verifySecret(myPassword); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QCOMPARE(secretVerifiedSignal.count(), 1); QCOMPARE(secretVerifiedSignal.at(0).at(0).toBool(), true); secretVerifiedSignal.clear(); /* Now get the info, and re-store the identity */ const char *infoSignature = SIGNAL(info(const SignOn::IdentityInfo &)); connect(identity, infoSignature, &m_identityResult, SLOT(info(const SignOn::IdentityInfo &))); connect(identity, infoSignature, &loop, SLOT(quit()), Qt::QueuedConnection); identity->queryInfo(); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QVERIFY2(m_identityResult.m_responseReceived != TestIdentityResult::InexistentResp, "A response was not received."); QCOMPARE(m_identityResult.m_idInfo.isStoringSecret(), true); QCOMPARE(m_identityResult.m_idInfo.secret(), QString()); /* Write it back, and verify that the password doesn't change. * Change the username to make sure that this is not a no-op. */ QString myUserName("Bob"); m_identityResult.m_idInfo.setUserName(myUserName); identity->storeCredentials(m_identityResult.m_idInfo); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); /* check that the store succeeded */ QCOMPARE(errorSignal.count(), 0); QCOMPARE(credentialsStoredSignal.count(), 1); credentialsStoredSignal.clear(); identity->verifySecret(myPassword); QTimer::singleShot(test_timeout, &loop, SLOT(quit())); loop.exec(); QCOMPARE(secretVerifiedSignal.count(), 1); QCOMPARE(secretVerifiedSignal.at(0).at(0).toBool(), true); delete identity; TEST_DONE } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); SignOnUI signOnUI(QDBusConnection::sessionBus()); int ret; SsoTestClient ssoTestClient(&signOnUI); ret = QTest::qExec(&ssoTestClient, argc, argv); if (ret != 0) return ret; TestAuthSession testAuthSession(&signOnUI); ret = QTest::qExec(&testAuthSession, argc, argv); return ret; } signond-nicolasfella/tests/libsignon-qt-tests/ssotestclient.h0000664000175000017500000000540014615454535025042 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SSOTESTCLIENT_H #define SSOTESTCLIENT_H #include #include "testauthsession.h" #include "testidentityresult.h" #include "testauthserviceresult.h" #include "SignOn/signonerror.h" class SignOnUI; class SsoTestClient: public QObject { Q_OBJECT public: SsoTestClient(SignOnUI *signOnUi, QObject *parent = 0); private Q_SLOTS: void initTestCase(); void cleanupTestCase(); /* * AuthService tests */ void queryIdentities(); void queryMethods(); void queryMechanisms(); void clear(); /* * Identity tests */ void queryAvailableMetods(); void storeCredentials_data(); void storeCredentials(); void requestCredentialsUpdate(); void queryInfo(); void addReference(); void removeReference(); void verifyUser(); void verifySecret(); void signOut(); void remove(); void sessionTest(); void multipleRemove(); void removeStoreRemove(); void queryAuthPluginACL(); void emptyPasswordRegression(); private: void clearDB(); void initAuthServiceTest(); void queryIdentitiesWithFilter(); /* * Subtests * */ bool testUpdatingCredentials(bool addMethods = true); bool testAddingNewCredentials(bool addMethods = true); /* * Helpers * */ static QString errCodeAsStr(const Error::ErrorType); bool storeCredentialsPrivate(const SignOn::IdentityInfo &info); QString pluginsDir() const; protected Q_SLOTS: void response(const SignOn::SessionData &data); private: SignOnUI *m_signOnUI; QStringList m_tokenList; int m_expectedNumberOfMethods; QStringList m_expectedMechanisms; int m_numberOfInsertedCredentials; quint32 m_storedIdentityId; IdentityInfo m_storedIdentityInfo; QString m_methodToQueryMechanisms; TestIdentityResult m_identityResult; TestAuthServiceResult m_serviceResult; }; #endif // SSOTESTCLIENT_H signond-nicolasfella/tests/libsignon-qt-tests/testauthserviceresult.cpp0000664000175000017500000000516014615454535027156 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "testauthserviceresult.h" #include #define SIGNOND_TEST_REPLY_RECEIVED qDebug() << "Reply from SIGNON DAEMON---------------------------------" << __FUNCTION__; TestAuthServiceResult::TestAuthServiceResult() { reset(); } void TestAuthServiceResult::reset() { m_responseReceived = InexistentResp; m_error = Error::Unknown; m_errMsg = QString(); m_identities.clear(); m_methods.clear(); m_mechanisms.first = QString(); m_mechanisms.second.clear(); m_cleared = false; } void TestAuthServiceResult::error(const SignOn::Error &error) { SIGNOND_TEST_REPLY_RECEIVED m_responseReceived = ErrorResp; m_error = (Error::ErrorType)error.type(); m_errMsg = error.message(); qDebug() << "Error:" << m_error << ", Message:" << m_errMsg; emit testCompleted(); } void TestAuthServiceResult::methodsAvailable(const QStringList &methods) { SIGNOND_TEST_REPLY_RECEIVED m_responseReceived = NormalResp; m_methods = methods; emit testCompleted(); } void TestAuthServiceResult::mechanismsAvailable(const QString &method, const QStringList &mechanisms) { SIGNOND_TEST_REPLY_RECEIVED m_responseReceived = NormalResp; m_mechanisms.first = method; m_mechanisms.second = mechanisms; m_queriedMechsMethod = method; emit testCompleted(); } void TestAuthServiceResult::identities( const QList &identityList) { SIGNOND_TEST_REPLY_RECEIVED m_responseReceived = NormalResp; m_identities = identityList; emit testCompleted(); } void TestAuthServiceResult::cleared() { SIGNOND_TEST_REPLY_RECEIVED m_responseReceived = NormalResp; m_cleared = true; emit testCompleted(); } signond-nicolasfella/tests/libsignon-qt-tests/testauthserviceresult.h0000664000175000017500000000364614615454535026632 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef TESTAUTHSERVICERESULT_H #define TESTAUTHSERVICERESULT_H #include #include "SignOn/authservice.h" #include "SignOn/identity.h" #include "SignOn/signonerror.h" using namespace SignOn; class TestAuthServiceResult: public QObject { Q_OBJECT public : enum ResponseType { NormalResp = 0, ErrorResp, InexistentResp }; public: Error::ErrorType m_error; QString m_errMsg; ResponseType m_responseReceived; QList m_identities; QStringList m_methods; QPair m_mechanisms; bool m_cleared; QString m_queriedMechsMethod; public: TestAuthServiceResult(); void reset(); public Q_SLOTS: void error(const SignOn::Error &err); void methodsAvailable(const QStringList &methods); void mechanismsAvailable(const QString &method, const QStringList &mechanisms); void identities(const QList &identityList); void cleared(); Q_SIGNALS: void testCompleted(); }; #endif // TESTAUTHSERVICERESULT_H signond-nicolasfella/tests/libsignon-qt-tests/testauthsession.cpp0000664000175000017500000006375114615454535025754 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "signon-ui.h" #include "testauthsession.h" #include "testthread.h" #include "SignOn/identity.h" #include #include #include #define SSO_TEST_CREATE_AUTH_SESSION(__session__, __method__) \ do { \ Identity *id = Identity::newIdentity(IdentityInfo(), this); \ __session__ = id->createSession(QLatin1String(__method__)); \ } while(0) static AuthSession *g_currentSession = NULL; static QStringList g_processReplyRealmsList; static int g_bigStringSize = 50000; static int g_bigStringReplySize = 0; TestAuthSession::TestAuthSession(SignOnUI *signOnUI, QObject *parent): QObject(parent), m_signOnUI(signOnUI) { } void TestAuthSession::initTestCase() { qDebug() << "HI!"; } void TestAuthSession::cleanupTestCase() { qDebug() << "BYE!"; } void TestAuthSession::sessionData() { QVariantMap originalMap; originalMap["Hello"] = "World"; originalMap["Int"] = 4; SessionData sessionData(originalMap); QCOMPARE(sessionData.toMap(), originalMap); } void TestAuthSession::queryMechanisms_existing_method() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); QStringList wantedMechs; QSignalSpy spy(as, SIGNAL(mechanismsAvailable(const QStringList&))); QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(mechanismsAvailable(const QStringList&)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); as->queryAvailableMechanisms(wantedMechs); if (!errorCounter.count()) loop.exec(); errorCounter.clear(); QCOMPARE(spy.count(), 1); QStringList result = spy.at(0).at(0).toStringList(); QCOMPARE(result.size(), 4); wantedMechs += "mech1"; QTimer::singleShot(10*1000, &loop, SLOT(quit())); as->queryAvailableMechanisms(wantedMechs); if (!errorCounter.count()) loop.exec(); errorCounter.clear(); QCOMPARE(spy.count(), 2); result = spy.at(1).at(0).toStringList(); QCOMPARE(result.size(), 1); wantedMechs += "mech2"; QTimer::singleShot(10*1000, &loop, SLOT(quit())); as->queryAvailableMechanisms(wantedMechs); if (!errorCounter.count()) loop.exec(); errorCounter.clear(); QCOMPARE(spy.count(), 3); result = spy.at(2).at(0).toStringList(); QCOMPARE(result.size(), 2); wantedMechs = QStringList("fake"); QTimer::singleShot(10*1000, &loop, SLOT(quit())); as->queryAvailableMechanisms(wantedMechs); if (!errorCounter.count()) loop.exec(); errorCounter.clear(); QCOMPARE(spy.count(), 4); result = spy.at(3).at(0).toStringList(); QCOMPARE(result.size(), 0); } void TestAuthSession::queryMechanisms_nonexisting_method() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "nonexisting"); QStringList wantedMechs; QSignalSpy spy(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(mechanismsAvailable(const QStringList&)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); as->queryAvailableMechanisms(wantedMechs); loop.exec(); QCOMPARE(spy.count(), 1); } void TestAuthSession::process_with_new_identity() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); g_processReplyRealmsList.clear(); connect(as, SIGNAL(response(const SignOn::SessionData &)), this, SLOT(response(const SignOn::SessionData &))); QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData &))); QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &))); QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&))); QEventLoop loop; QObject::connect(as, SIGNAL(response(const SignOn::SessionData &)), &loop, SLOT(quit()), Qt::QueuedConnection); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(stateCounter.count(), 12); stateCounter.clear(); errorCounter.clear(); as->process(inData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(stateCounter.count(), 12); stateCounter.clear(); errorCounter.clear(); as->process(inData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(stateCounter.count(), 12); stateCounter.clear(); errorCounter.clear(); as->process(inData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(stateCounter.count(), 12); stateCounter.clear(); errorCounter.clear(); QCOMPARE(spy.count(), 4); QVERIFY(g_processReplyRealmsList.at(0) == "testRealm_after_test"); QVERIFY(g_processReplyRealmsList.at(1) == "testRealm_after_test"); QVERIFY(g_processReplyRealmsList.at(2) == "testRealm_after_test"); QVERIFY(g_processReplyRealmsList.at(3) == "testRealm_after_test"); } void TestAuthSession::process_with_existing_identity() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); g_processReplyRealmsList.clear(); connect(as, SIGNAL(response(const SignOn::SessionData &)), this, SLOT(response(const SignOn::SessionData &))); QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &))); QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&))); QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData&))); QEventLoop loop; QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(stateCounter.count(), 12); stateCounter.clear(); errorCounter.clear(); as->process(inData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(stateCounter.count(), 12); stateCounter.clear(); errorCounter.clear(); as->process(inData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(stateCounter.count(), 12); stateCounter.clear(); errorCounter.clear(); as->process(inData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(stateCounter.count(), 12); stateCounter.clear(); errorCounter.clear(); QCOMPARE(spy.count(), 4); QVERIFY(g_processReplyRealmsList.at(0) == "testRealm_after_test"); QVERIFY(g_processReplyRealmsList.at(1) == "testRealm_after_test"); QVERIFY(g_processReplyRealmsList.at(2) == "testRealm_after_test"); QVERIFY(g_processReplyRealmsList.at(3) == "testRealm_after_test"); } void TestAuthSession::process_with_nonexisting_type() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "nonexisting"); QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData &))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&))); QEventLoop loop; QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()), Qt::QueuedConnection); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); loop.exec(); as->process(inData, "mech1"); loop.exec(); as->process(inData, "mech1"); loop.exec(); as->process(inData, "mech1"); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 4); QVERIFY(stateCounter.count() <= 4); } void TestAuthSession::process_with_nonexisting_method() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&))); QEventLoop loop; QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()), Qt::QueuedConnection); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "nonexisting"); loop.exec(); as->process(inData, "nonexisting"); loop.exec(); as->process(inData, "nonexisting"); loop.exec(); as->process(inData, "nonexisting"); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 4); QCOMPARE(stateCounter.count(), 8); } void TestAuthSession::process_with_unauthorized_method() { MechanismsList mechs; mechs.append("mech1"); QMap methods; methods.insert(QLatin1String("ssotest"), mechs); IdentityInfo info("test_caption", "test_user_name", methods); info.setSecret("test_secret"); info.setAccessControlList(QStringList() << "*"); Identity *id = Identity::newIdentity(info, this); QSignalSpy spyResponseStoreCreds(id, SIGNAL(credentialsStored(const quint32))); QSignalSpy spyErrorStoreCreds(id, SIGNAL(error(const SignOn::Error &))); QEventLoop loopStoreCreds; QObject::connect(id, SIGNAL(error(const SignOn::Error &)), &loopStoreCreds, SLOT(quit()), Qt::QueuedConnection); QObject::connect(id, SIGNAL(credentialsStored(const quint32)), &loopStoreCreds, SLOT(quit())); QTimer::singleShot(10*1000, &loopStoreCreds, SLOT(quit())); id->storeCredentials(); loopStoreCreds.exec(); QCOMPARE(spyResponseStoreCreds.count(), 1); QCOMPARE(spyErrorStoreCreds.count(), 0); AuthSession *as = id->createSession(QLatin1String("ssotest")); QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData &))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()), Qt::QueuedConnection); QObject::connect(as, SIGNAL(response(const SignOn::SessionData &)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; as->process(inData, "mech2"); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 1); // Still make sure the error really was about bad auth method/mechanism SignOn::Error::ErrorType errorType = SignOn::Error::Unknown; QVariant var = spyError.at(0).at(0); if (QLatin1String("SignOn::Error") == var.typeName()) { SignOn::Error error = var.value(); errorType = (SignOn::Error::ErrorType)error.type(); } QCOMPARE(errorType, SignOn::Error::MethodOrMechanismNotAllowed); } void TestAuthSession::process_many_times_after_auth() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); loop.exec(); QCOMPARE(spyResponse.count(), 1); as->process(inData, "mech1"); as->process(inData, "mech1"); as->process(inData, "mech1"); as->process(inData, "mech1"); loop.exec(); QCOMPARE(spyResponse.count(), 2); QCOMPARE(spyError.count(), 3); as->process(inData, "mech1"); as->process(inData, "mech1"); as->process(inData, "mech1"); as->process(inData, "mech1"); loop.exec(); QCOMPARE(spyResponse.count(), 3); QCOMPARE(spyError.count(), 6); as->process(inData, "mech1"); as->process(inData, "mech1"); as->process(inData, "mech1"); as->process(inData, "mech1"); loop.exec(); QCOMPARE(spyResponse.count(), 4); QCOMPARE(spyError.count(), 9); } void TestAuthSession::process_many_times_before_auth() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); as->process(inData, "mech1"); as->process(inData, "mech1"); as->process(inData, "mech1"); loop.exec(); QCOMPARE(spyError.count(), 3); QCOMPARE(spyResponse.count(), 1); } void TestAuthSession::process_with_big_session_data() { //TODO once bug Bug#222200 is fixed, this test case can be enabled QSKIP("This test requires fix", SkipSingle); AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), this, SLOT(response(const SignOn::SessionData&))); QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); QString bigString; bigString.fill(QChar('A'), g_bigStringSize); inData.setCaption(bigString); as->process(inData, "BLOB"); loop.exec(); QCOMPARE(spyError.count(), 0); QCOMPARE(spyResponse.count(), 1); QCOMPARE(g_bigStringReplySize, g_bigStringSize); } void TestAuthSession::process_after_timeout() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit())); QTimer::singleShot(20*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); loop.exec(); QCOMPARE(spyResponse.count(), 1); QCOMPARE(spyError.count(), 0); spyResponse.clear(); // Wait for auto-destruction of the remote object QTest::qWait(6000); /* Create an authsession just to trigger the actual destruction of the * first. */ AuthSession *as2; SSO_TEST_CREATE_AUTH_SESSION(as2, "ssotest"); Q_UNUSED(as2); // Try processing again as->process(inData, "mech1"); loop.exec(); QCOMPARE(spyResponse.count(), 1); QCOMPARE(spyError.count(), 0); } void TestAuthSession::cancel_immediately() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()), Qt::QueuedConnection); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); as->cancel(); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 1); as->process(inData, "mech1"); as->cancel(); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 2); as->process(inData, "mech1"); as->cancel(); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 3); as->process(inData, "mech1"); as->cancel(); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 4); } void TestAuthSession::cancel_with_delay() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); g_currentSession = as; QSignalSpy spyResponse(as, SIGNAL(response(const SignOn::SessionData&))); QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); QTimer::singleShot(0.1*1000, this, SLOT(cancel())); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 1); as->process(inData, "mech1"); QTimer::singleShot(0.1*1000, this, SLOT(cancel())); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 2); as->process(inData, "mech1"); QTimer::singleShot(0.1*1000, this, SLOT(cancel())); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 3); as->process(inData, "mech1"); QTimer::singleShot(0.1*1000, this, SLOT(cancel())); loop.exec(); QCOMPARE(spyResponse.count(), 0); QCOMPARE(spyError.count(), 4); } void TestAuthSession::cancel_without_process() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); g_currentSession = as; QSignalSpy spyError(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit()), Qt::QueuedConnection); QTimer::singleShot(10*1000, &loop, SLOT(quit())); QTimer::singleShot(1*1000, &loop, SLOT(quit())); as->cancel(); loop.exec(); QCOMPARE(spyError.count(), 0); QTimer::singleShot(1*1000, &loop, SLOT(quit())); QTimer::singleShot(0.1*1000, this, SLOT(cancel())); loop.exec(); QCOMPARE(spyError.count(), 0); QTimer::singleShot(0.1*1000, this, SLOT(cancel())); QTimer::singleShot(1*1000, &loop, SLOT(quit())); loop.exec(); QCOMPARE(spyError.count(), 0); SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); as->process(inData, "mech1"); as->cancel(); as->cancel(); as->cancel(); loop.exec(); QCOMPARE(spyError.count(), 1); } void TestAuthSession::handle_destroyed_signal() { QSKIP("testing in sb", SkipSingle); AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest"); g_currentSession = as; QSignalSpy spy(as, SIGNAL(mechanismsAvailable(const QStringList&))); QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &))); QEventLoop loop; QObject::connect(as, SIGNAL(mechanismsAvailable(const QStringList&)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); /* * 5 minutes + 10 seconds * */ QTimer::singleShot(5 * 62 *1000, &loop, SLOT(quit())); loop.exec(); QTimer::singleShot(5 * 1000, &loop, SLOT(quit())); loop.exec(); QStringList wantedMechs; as->queryAvailableMechanisms(wantedMechs); if (!errorCounter.count()) loop.exec(); QCOMPARE(spy.count(), 1); QStringList result = spy.at(0).at(0).toStringList(); QCOMPARE(result.size(), 4); } void TestAuthSession::multi_thread_test() { //execute a SignOn call in a separate thread TestThread thread; thread.start(); thread.wait(g_testThreadTimeout + 1000); //do the same in this thread - this test succeeds if the //following succeeds process_with_new_identity(); } void TestAuthSession::cancel() { g_currentSession->cancel(); } void TestAuthSession::response(const SignOn::SessionData &data) { g_processReplyRealmsList << data.Realm(); g_bigStringReplySize = data.Caption().size(); } void TestAuthSession::processUi_with_existing_identity() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest2"); QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &))); QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&))); QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData&))); QEventLoop loop; QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(500*1000, &loop, SLOT(quit())); /* * chain of UiSessionData * */ QStringList chainOfStates; SsoTest2PluginNS::SsoTest2Data testData; chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha"; chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha"; chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha"; chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha"; testData.setChainOfStates(chainOfStates); testData.setCurrentState(0); as->process(testData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(spy.count(), 1); if (errorCounter.count()) qDebug() << errorCounter.at(0).at(1).toString(); QCOMPARE(errorCounter.count(), 0); SignOn::SessionData outData = spy.at(0).at(0).value(); SsoTest2PluginNS::SsoTest2Data resultData = outData.data(); foreach(QString result, resultData.ChainOfResults()) QCOMPARE(result, QString("OK")); } void TestAuthSession::processUi_and_cancel() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest2"); g_currentSession = as; m_signOnUI->setDelay(4); QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &))); QSignalSpy stateCounter(as, SIGNAL(stateChanged(AuthSession::AuthSessionState, const QString&))); QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData&))); QEventLoop loop; QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(500*1000, &loop, SLOT(quit())); /* * chain of UiSessionData * */ QStringList chainOfStates; SsoTest2PluginNS::SsoTest2Data testData; chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha"; chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha"; chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha"; chainOfStates << "Browser" <<"Login" << "Captcha" << "LoginAndCaptcha"; testData.setChainOfStates(chainOfStates); testData.setCurrentState(0); as->process(testData, "mech1"); QTimer::singleShot(3*1000, this, SLOT(cancel())); if (!errorCounter.count()) loop.exec(); QCOMPARE(spy.count(), 0); QCOMPARE(errorCounter.count(), 1); m_signOnUI->setDelay(0); } void TestAuthSession::windowId() { AuthSession *as; SSO_TEST_CREATE_AUTH_SESSION(as, "ssotest2"); QSignalSpy errorCounter(as, SIGNAL(error(const SignOn::Error &))); QSignalSpy spy(as, SIGNAL(response(const SignOn::SessionData&))); QEventLoop loop; QObject::connect(as, SIGNAL(response(const SignOn::SessionData&)), &loop, SLOT(quit())); QObject::connect(as, SIGNAL(error(const SignOn::Error &)), &loop, SLOT(quit())); QTimer::singleShot(500*1000, &loop, SLOT(quit())); /* * chain of UiSessionData * */ QStringList chainOfStates; SsoTest2PluginNS::SsoTest2Data testData; chainOfStates << "Browser" << "Browser"; testData.setChainOfStates(chainOfStates); testData.setCurrentState(0); testData.setWindowId(0xdeadbeef); as->process(testData, "mech1"); if (!errorCounter.count()) loop.exec(); QCOMPARE(spy.count(), 1); QCOMPARE(errorCounter.count(), 0); QCOMPARE(m_signOnUI->clientData().value("WindowId").toUInt(), 0xdeadbeef); QCOMPARE(m_signOnUI->method(), QLatin1String("ssotest2")); QCOMPARE(m_signOnUI->mechanism(), QLatin1String("mech1")); } signond-nicolasfella/tests/libsignon-qt-tests/testauthsession.h0000664000175000017500000000716314615454535025414 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef TESTAUTHSESSION_H_ #define TESTAUTHSESSION_H_ #include #include #include #include #include #include "signond/signoncommon.h" #include "SignOn/authservice.h" #include "ssotest2data.h" #include "SignOn/uisessiondata.h" /* * here we test the implementation because of difficulties of having * access to protected/private functions * */ #include "SignOn/authsessionimpl.h" using namespace SignOn; /* * test timeout 10 seconds * */ #define test_timeout 10000 class SignOnUI; class TestAuthSession: public QObject { Q_OBJECT public: TestAuthSession(SignOnUI *signOnUi, QObject *parent = 0); private Q_SLOTS: /* * Start the signon daemon */ void initTestCase(); /* * End the signon daemon */ void cleanupTestCase(); /* * UIless * AuthSession API related test cases */ void sessionData(); void queryMechanisms_existing_method(); void queryMechanisms_nonexisting_method(); void process_with_new_identity(); void process_with_existing_identity(); void process_with_nonexisting_type(); void process_with_nonexisting_method(); void process_with_unauthorized_method(); void process_many_times_after_auth(); void process_many_times_before_auth(); void process_with_big_session_data(); void process_after_timeout(); void cancel_immediately(); void cancel_with_delay(); void cancel_without_process(); void handle_destroyed_signal(); void multi_thread_test(); void processUi_with_existing_identity(); void processUi_and_cancel(); void windowId(); private Q_SLOTS: void cancel(); void response(const SignOn::SessionData &data); private: SignOnUI *m_signOnUI; }; /* * The SlotMachine class is used by process_from_other_process * test to receive signals regarding the completion of D-Bus * calls. The QSignalSpy classes cannot be used because the * class for the D-Bus methods must have both response method * and error method. */ class SlotMachine: public QObject { Q_OBJECT public: SlotMachine(): m_responseReceived(false) {} public Q_SLOTS: void authenticationSlot(const QString &path) { m_path = path; emit done(); } void errorSlot(const QDBusError &err) { m_errorMessage = err.message(); m_errorName = err.name(); emit done(); } void responseSlot(const QVariantMap &response) { m_response = response; m_responseReceived = true; emit done(); } Q_SIGNALS: void done(); public: QString m_path; QString m_errorMessage; QString m_errorName; QVariantMap m_response; bool m_responseReceived; }; #endif signond-nicolasfella/tests/libsignon-qt-tests/testidentityresult.cpp0000664000175000017500000001150614615454535026466 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "testidentityresult.h" #define IT_IS_HAPPENING qDebug() << "Reply from SIGNON DAEMON---------------------------------" << __FUNCTION__; TestIdentityResult::TestIdentityResult() { reset(); } void TestIdentityResult::reset() { m_responseReceived = InexistentResp; m_error = Error::Unknown; m_errMsg = QString(); m_methods.clear(); m_id = 0; m_idInfo = IdentityInfo(); m_userVerified = false; m_secretVerified = false; m_signedOut = false; m_removed = false; } bool TestIdentityResult::compareIdentityInfos(const IdentityInfo &info1, const IdentityInfo &info2, bool checkId, bool checlACL) { qDebug() << QString("Comparing identities %1 & %2."). arg(info1.id()).arg(info2.id()); if (checkId && (info1.id() != info2.id())) { qDebug() << "IDs:" << info1.id() << " " << info2.id(); return false; } if (info1.caption() != info2.caption()) { qDebug() << "Captions:" << info1.caption() << " " << info2.caption(); return false; } if (info1.methods() != info2.methods()) { qDebug() << "Methods:" << info1.methods() << " " << info2.methods(); return false; } if (info1.realms() != info2.realms()) { qDebug() << "Realms:" << info1.realms() << " " << info2.realms(); return false; } if (checlACL && (info1.accessControlList() != info2.accessControlList())) { qDebug() << "ACLs:" << info1.accessControlList() << " " << info2.accessControlList(); return false; } if (info1.userName() != info2.userName()) { qDebug() << "Usernames:" << info1.userName() << " " << info2.userName(); return false; } foreach (QString method, info1.methods()) { MechanismsList mechs1 = info1.mechanisms(method); MechanismsList mechs2 = info2.mechanisms(method); mechs1.sort(); mechs2.sort(); if (mechs1 != mechs2) { qDebug() << QString("Mechanisms for method %1:").arg(method) << info1.mechanisms(method) << " " << info2.mechanisms(method); return false; } } return true; } void TestIdentityResult::error(const SignOn::Error& error) { m_responseReceived = ErrorResp; m_error = (Error::ErrorType)error.type(); m_errMsg = error.message(); qDebug() << "Error:" << m_error << ", Message:" << m_errMsg; emit testCompleted(); } void TestIdentityResult::methodsAvailable(const QStringList& methods) { IT_IS_HAPPENING m_responseReceived = NormalResp; m_methods = methods; emit testCompleted(); } void TestIdentityResult::credentialsStored(const quint32 id) { IT_IS_HAPPENING m_responseReceived = NormalResp; m_id = id; emit testCompleted(); } void TestIdentityResult::info(const IdentityInfo &info) { IT_IS_HAPPENING m_responseReceived = NormalResp; m_idInfo = info; emit testCompleted(); } void TestIdentityResult::userVerified(const bool valid) { IT_IS_HAPPENING m_responseReceived = NormalResp; m_userVerified = valid; emit testCompleted(); } void TestIdentityResult::secretVerified(const bool valid) { IT_IS_HAPPENING m_responseReceived = NormalResp; m_secretVerified = valid; emit testCompleted(); } void TestIdentityResult::removed() { IT_IS_HAPPENING m_responseReceived = NormalResp; m_removed = true; emit testCompleted(); } void TestIdentityResult::signedOut() { IT_IS_HAPPENING m_responseReceived = NormalResp; m_signedOut = true; emit testCompleted(); } void TestIdentityResult::referenceAdded() { IT_IS_HAPPENING m_responseReceived = NormalResp; m_removed = true; emit testCompleted(); } void TestIdentityResult::referenceRemoved() { IT_IS_HAPPENING m_responseReceived = NormalResp; m_removed = true; emit testCompleted(); } signond-nicolasfella/tests/libsignon-qt-tests/testidentityresult.h0000664000175000017500000000433514615454535026135 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef TESTSIDENTITYRESULT_H #define TESTSIDENTITYRESULT_H #include #include "SignOn/authservice.h" #include "SignOn/identity.h" #include "SignOn/signonerror.h" using namespace SignOn; class TestIdentityResult: public QObject { Q_OBJECT public : enum ResponseType { NormalResp = 0, ErrorResp, InexistentResp }; public: Error::ErrorType m_error; QString m_errMsg; ResponseType m_responseReceived; QStringList m_methods; quint32 m_id; IdentityInfo m_idInfo; bool m_userVerified; bool m_secretVerified; bool m_signedOut; bool m_removed; public: TestIdentityResult(); void reset(); static bool compareIdentityInfos(const IdentityInfo &info1, const IdentityInfo &info2, bool checkId = false, bool checlACL = false); public Q_SLOTS: void error(const SignOn::Error &err); void methodsAvailable(const QStringList &methods); void credentialsStored(const quint32 id); void info(const SignOn::IdentityInfo& info); void userVerified(const bool valid); void secretVerified(const bool valid); void removed(); void signedOut(); void referenceAdded(); void referenceRemoved(); Q_SIGNALS: void testCompleted(); }; #endif // TESTSIDENTITYRESULT_H signond-nicolasfella/tests/libsignon-qt-tests/testsinglesignon.cpp0000664000175000017500000001046614615454535026101 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include "testsinglesignon.h" #include "ssotestclient.h" #include "ssoclientthread.h" #include void TestSingleSignon::initTestCase() { m_numberOfTestClients = NUMBER_OF_TEST_CLIENTS; } void TestSingleSignon::cleanupTestCase() { } void TestSingleSignon::singleTestClient() { QTime startTime = QTime::currentTime(); SsoTestClient client; client.runAllTests(); QTime endTime = QTime::currentTime(); int elapsed = startTime.secsTo(endTime); qDebug() << QString("TestSingleSignon::singleTestClient() " "---- TIME --> Total elapsed time: %1 seconds."). arg(elapsed); } void TestSingleSignon::multipleClientsAtOnceTest() { QList clientThreads; QTime startTime = QTime::currentTime(); for(int i = 0; i < m_numberOfTestClients; i++) { qDebug() << "Creating SSO test client thread..."; SsoClientThread *thread = new SsoClientThread(SsoTestClient::AllTests); thread->start(); clientThreads.append(thread); } SsoClientThread *thread = NULL; bool done = false; //this assumes all client threads will be finished at a certain point while(!done) { int finishedThreadsCount = 0; foreach(thread, clientThreads) if(thread->isFinished()) ++finishedThreadsCount; done = ((finishedThreadsCount == m_numberOfTestClients) ? true : false); sleep(1); } while(!clientThreads.empty()) if(SsoClientThread *thread = clientThreads.takeFirst()) delete thread; QTime endTime = QTime::currentTime(); int elapsed = startTime.secsTo(endTime); qDebug() << QString("TestSingleSignon::multipleClientsAtOnceTest() " "---- TIME --> Total elapsed time: %1 seconds."). arg(elapsed); } void TestSingleSignon::multipleClientsAtOnceContiousTest() { QTime startTime = QTime::currentTime(); int rounds = 5; while(rounds > 0) { QList clientThreads; for (int i = 0; i < m_numberOfTestClients; i++) { qDebug() << "\n\nCreating SSO test client thread..."; SsoClientThread *thread = new SsoClientThread(SsoTestClient::AllTests); thread->start(); clientThreads.append(thread); } SsoClientThread *thread = NULL; bool done = false; //this assumes all client threads will be finished at a certain point while (!done) { int finishedThreadsCount = 0; foreach(thread, clientThreads) if (thread->isFinished()) ++finishedThreadsCount; done = ((finishedThreadsCount == m_numberOfTestClients) ? true : false); sleep(1); } while (!clientThreads.empty()) if (SsoClientThread *thread = clientThreads.takeFirst()) delete thread; --rounds; } QTime endTime = QTime::currentTime(); int elapsed = startTime.secsTo(endTime); qDebug() << QString("TestSingleSignon::multipleClientsAtOnceContiousTest() " "---- TIME --> Total elapsed time: %1 seconds."). arg(elapsed); } void TestSingleSignon::stressTest() { //think of something awful here } #ifndef SSO_CI_TESTMANAGEMENT QTEST_MAIN(TestSingleSignon) #endif signond-nicolasfella/tests/libsignon-qt-tests/testsinglesignon.h0000664000175000017500000000263114615454535025541 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef TESTSINGLESIGNON_H #define TESTSINGLESIGNON_H #include class QProcess; class TestSingleSignon: public QObject { Q_OBJECT private Q_SLOTS: /* * Start the signon daemon */ void initTestCase(); /* * End the signon daemon */ void cleanupTestCase(); /* * Test cases */ void singleTestClient(); void multipleClientsAtOnceTest(); private: void multipleClientsAtOnceContiousTest(); void stressTest(); private: int m_numberOfTestClients; }; #endif // TESTSINGLESIGNON_H signond-nicolasfella/tests/libsignon-qt-tests/testthread.cpp0000664000175000017500000000325014615454535024642 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "testthread.h" #include "SignOn/authservice.h" #include #include using namespace SignOn; void TestThread::run() { /* Just call any method on the SignOn API so that the session bus connection is created in this thread, a different one from the main thread. */ AuthService service; QEventLoop loop; connect(&service, SIGNAL(methodsAvailable(const QStringList &)), SIGNAL(testCompleted())); connect(&service, SIGNAL(error(const SignOn::Error &)), SIGNAL(testCompleted())); connect(this, SIGNAL(testCompleted()), &loop, SLOT(quit())); service.queryMethods(); QTimer::singleShot(g_testThreadTimeout, &loop, SLOT(quit())); loop.exec(); } signond-nicolasfella/tests/libsignon-qt-tests/testthread.h0000664000175000017500000000212714615454535024311 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include const int g_testThreadTimeout = 10000; class TestThread: public QThread { Q_OBJECT public: void run(); Q_SIGNALS: void testCompleted(); }; signond-nicolasfella/tests/libsignon-qt-tests/libsignon-qt-tests.pro0000664000175000017500000000177014615454547026267 0ustar coucoufcoucoufinclude( ../tests.pri ) TARGET = libsignon-qt-tests CONFIG += \ build_all QT += \ core \ dbus \ testlib QT -= gui LIBS *= -lsignon-qt$${QT_MAJOR_VERSION} QMAKE_LIBDIR += $${TOP_BUILD_DIR}/lib/SignOn QMAKE_RPATHDIR = $${QMAKE_LIBDIR} SOURCES += \ testauthsession.cpp \ testthread.cpp \ signon-ui.cpp \ ssotestclient.cpp \ testauthserviceresult.cpp \ testidentityresult.cpp HEADERS += \ testauthsession.h \ testthread.h \ signon-ui.h \ ssotestclient.h \ testauthserviceresult.h \ testidentityresult.h \ $$TOP_SRC_DIR/src/plugins/test/ssotest2data.h INCLUDEPATH += . \ $$TOP_SRC_DIR/lib \ $$TOP_SRC_DIR/lib/plugins \ $$TOP_SRC_DIR/src/plugins/test DEFINES += SSO_CI_TESTMANAGEMENT DEFINES += "SIGNOND_PLUGINS_DIR=$${SIGNOND_PLUGINS_DIR_QUOTED}" check.depends = $$TARGET check.commands = "SSO_PLUGINS_DIR=$${TOP_BUILD_DIR}/src/plugins/test SSO_EXTENSIONS_DIR=$${TOP_BUILD_DIR}/non-existing-dir $$RUN_WITH_SIGNOND ./libsignon-qt-tests" signond-nicolasfella/tests/passwordplugintest/0000775000175000017500000000000014615454535022202 5ustar coucoufcoucoufsignond-nicolasfella/tests/passwordplugintest/passwordplugintest.cpp0000664000175000017500000001563414615454535026700 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "passwordplugin.h" #include "passwordplugin.cpp" #include "passwordplugintest.h" using namespace PasswordPluginNS; #define TEST_START qDebug("\n\n\n\n ----------------- %s ----------------\n\n", __func__); #define TEST_DONE qDebug("\n\n ----------------- %s DONE ----------------\n\n", __func__); void PasswordPluginTest::initTestCase() { TEST_START qRegisterMetaType(); qRegisterMetaType(); TEST_DONE } void PasswordPluginTest::cleanupTestCase() { TEST_START TEST_DONE } //prepare each test by creating new plugin void PasswordPluginTest::init() { m_testPlugin = new PasswordPlugin(); } //finnish each test by deleting plugin void PasswordPluginTest::cleanup() { delete m_testPlugin; m_testPlugin=NULL; } //slot for receiving result void PasswordPluginTest::result(const SignOn::SessionData &data) { qDebug() << "got result"; m_response = data; m_loop.exit(); } //slot for receiving error void PasswordPluginTest::pluginError(const SignOn::Error &err) { qDebug() << "got error" << err.type() << ": " << err.message(); m_error = err.type(); m_loop.exit(); } //slot for receiving result void PasswordPluginTest::uiRequest(const SignOn::UiSessionData &data) { qDebug() << "got ui request"; m_uiResponse = data; m_loop.exit(); } //test cases void PasswordPluginTest::testPlugin() { TEST_START qDebug() << "Checking plugin integrity."; QVERIFY(m_testPlugin); TEST_DONE } void PasswordPluginTest::testPluginType() { TEST_START qDebug() << "Checking plugin type."; QCOMPARE(m_testPlugin->type(), QString("password")); TEST_DONE } void PasswordPluginTest::testPluginMechanisms() { TEST_START qDebug() << "Checking plugin mechanisms."; QStringList mechs = m_testPlugin->mechanisms(); QVERIFY(!mechs.isEmpty()); QVERIFY(mechs.contains(QString("password"))); qDebug() << mechs; TEST_DONE } void PasswordPluginTest::testPluginCancel() { TEST_START //no cancel functionality TEST_DONE } void PasswordPluginTest::testPluginProcess() { TEST_START SignOn::SessionData info; SignOn::SessionData info2; QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), this, SLOT(result(const SignOn::SessionData&)), Qt::QueuedConnection); QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), this, SLOT(pluginError(const SignOn::Error & )), Qt::QueuedConnection); QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), this, SLOT(uiRequest(const SignOn::UiSessionData&)), Qt::QueuedConnection); QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); //try with password info.setSecret(QString("pass")); m_testPlugin->process(info); m_loop.exec(); QVERIFY(m_response.Secret() == QString("pass")); QVERIFY(m_response.UserName().isEmpty()); //try with username info.setUserName(QString("user")); m_testPlugin->process(info); m_loop.exec(); QVERIFY(m_response.Secret() == QString("pass")); QVERIFY(m_response.UserName() == QString("user")); //try without params to open ui m_testPlugin->process(info2); m_loop.exec(); QVERIFY(m_uiResponse.QueryUserName() ); QVERIFY(m_uiResponse.QueryPassword() ); //try without password to open ui info2.setUserName(QString("user")); m_testPlugin->process(info2); m_loop.exec(); QVERIFY(!m_uiResponse.QueryUserName() ); QVERIFY(m_uiResponse.QueryPassword() ); TEST_DONE } void PasswordPluginTest::testPluginUserActionFinished() { TEST_START SignOn::UiSessionData info; QObject::connect(m_testPlugin, SIGNAL(result(const SignOn::SessionData&)), this, SLOT(result(const SignOn::SessionData&)), Qt::QueuedConnection); QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error & )), this, SLOT(pluginError(const SignOn::Error & )), Qt::QueuedConnection); QObject::connect(m_testPlugin, SIGNAL(userActionRequired(const SignOn::UiSessionData&)), this, SLOT(uiRequest(const SignOn::UiSessionData&)), Qt::QueuedConnection); QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); //empty data m_testPlugin->userActionFinished(info); m_loop.exec(); //fails because of ui error 0 is returned if not defined // QVERIFY(m_error == PLUGIN_ERROR_USER_INTERACTION); //correct values info.setQueryErrorCode(QUERY_ERROR_NONE); info.setUserName(QString("user") ); info.setSecret(QString("pass") ); m_testPlugin->userActionFinished(info); m_loop.exec(); QVERIFY(m_response.UserName() == QString("user") ); QVERIFY(m_response.Secret() == QString("pass") ); //user canceled info.setQueryErrorCode(QUERY_ERROR_CANCELED); m_testPlugin->userActionFinished(info); m_loop.exec(); QVERIFY(m_error == Error::SessionCanceled); //error in ui request info.setQueryErrorCode(QUERY_ERROR_GENERAL); m_testPlugin->userActionFinished(info); m_loop.exec(); QVERIFY(m_error == Error::UserInteraction); TEST_DONE } void PasswordPluginTest::testPluginRefresh() { TEST_START SignOn::UiSessionData info; QObject::connect(m_testPlugin, SIGNAL(error(const SignOn::Error &)), this, SLOT(pluginError(const SignOn::Error &)), Qt::QueuedConnection); QObject::connect(m_testPlugin, SIGNAL(refreshed(const SignOn::UiSessionData&)), this, SLOT(uiRequest(const SignOn::UiSessionData&)), Qt::QueuedConnection); QTimer::singleShot(10*1000, &m_loop, SLOT(quit())); m_testPlugin->refresh(info); m_loop.exec(); TEST_DONE } //end test cases QTEST_MAIN(PasswordPluginTest) signond-nicolasfella/tests/passwordplugintest/passwordplugintest.h0000664000175000017500000000347614615454535026346 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef PASSWORD_PLUGIN_TEST #define PASSWORD_PLUGIN_TEST #include #include "passwordplugin.h" using namespace PasswordPluginNS; class PasswordPluginTest: public QObject { Q_OBJECT public slots: void result(const SignOn::SessionData &data); void pluginError(const SignOn::Error &err); void uiRequest(const SignOn::UiSessionData &data); private slots: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); //test cases void testPlugin(); void testPluginType(); void testPluginMechanisms(); void testPluginCancel(); void testPluginProcess(); void testPluginUserActionFinished(); void testPluginRefresh(); //end test cases private: PasswordPlugin *m_testPlugin; int m_error; SignOn::SessionData m_response; SignOn::UiSessionData m_uiResponse; QEventLoop m_loop; }; #endif //PASSWORD_PLUGIN_TEST signond-nicolasfella/tests/passwordplugintest/passwordplugintest.pro0000664000175000017500000000071714615454535026712 0ustar coucoufcoucoufinclude( ../tests.pri ) TARGET = signon-passwordplugin-tests QT += core \ network \ testlib DEFINES += SIGNON_PLUGIN_TRACE SOURCES += passwordplugintest.cpp HEADERS += passwordplugintest.h \ $${TOP_SRC_DIR}/src/plugins/password/passwordplugin.h \ $${TOP_SRC_DIR}/lib/plugins/SignOn/authpluginif.h INCLUDEPATH += $${TOP_SRC_DIR}/lib/plugins \ $${TOP_SRC_DIR}/src/plugins/password \ $${TOP_SRC_DIR}/src/plugins \ $${TOP_SRC_DIR}/lib signond-nicolasfella/tests/run-with-signond.sh0000775000175000017500000000231514615454535021775 0ustar coucoufcoucouf#! /bin/sh # If there's already an instance of signond running, kill it set -e # start a local signond export HOME="$(mktemp -d -p /tmp signond-tests-XXXXXX)" export SSO_LOGGING_LEVEL=2 export SSO_STORAGE_PATH="${HOME}" export SSO_DAEMON_TIMEOUT=5 export SSO_IDENTITY_TIMEOUT=5 export SSO_AUTHSESSION_TIMEOUT=5 export PATH="${BUILDDIR}/src/remotepluginprocess:$PATH" export LD_LIBRARY_PATH="${BUILDDIR}/lib/plugins":"${BUILDDIR}/lib/plugins/signon-plugins-common":"${BUILDDIR}/lib/signond/SignOn":"$LD_LIBRARY_PATH" export XDG_RUNTIME_DIR="${HOME}/runtime-dir" mkdir -p "$XDG_RUNTIME_DIR" DBUS_CONFIG=${BUILDDIR}/tests/testsession.conf # If dbus-test-runner exists, use it to run the tests in a separate D-Bus # session if command -v dbus-test-runner > /dev/null ; then echo "Using dbus-test-runner" export SSO_LOGGING_OUTPUT="stdout" dbus-test-runner -m 600 --dbus-config=${DBUS_CONFIG} \ -t "$@" --keep-env else echo "Using dbus-launch" eval $(dbus-launch --sh-syntax --config-file=${DBUS_CONFIG}) cleanUp() { echo "Cleaning up." kill "$DBUS_SESSION_BUS_PID" } trap cleanUp EXIT INT TERM ${CLIENT_WRAPPER} $@ trap - EXIT cleanUp fi rm -rf ${HOME} signond-nicolasfella/tests/signond-tests/0000775000175000017500000000000014615454547021025 5ustar coucoufcoucoufsignond-nicolasfella/tests/signond-tests/access-control.pro0000664000175000017500000000017114615454535024462 0ustar coucoufcoucoufTEMPLATE = subdirs CONFIG += ordered SUBDIRS = \ mock-ac-plugin \ identity-tool.pro \ tst_access_control.pro signond-nicolasfella/tests/signond-tests/backuptest.cpp0000664000175000017500000001141614615454535023676 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "backuptest.h" #include "signond/signoncommon.h" #include #include void TestBackup::initTestCase() { /* daemonProcess = new QProcess(); daemonProcess->start("signond"); daemonProcess->waitForStarted(10 * 1000); */ } void TestBackup::cleanupTestCase() { /* daemonProcess->kill(); daemonProcess->waitForFinished(); delete daemonProcess; */ } void TestBackup::init() { //wait a bit between tests sleep(5); } void TestBackup::cleanup() { sleep(1); } void TestBackup::backupTest() { QDBusConnection conn (SIGNOND_BUS); //remove backup files QFile::remove("/home/user/.signon/signondb.bin"); QDBusMessage msg = QDBusMessage::createMethodCall(SIGNOND_SERVICE + ".Backup", SIGNOND_DAEMON_OBJECTPATH + "/Backup", "com.nokia.backupclient", "backupStarts"); QList args; msg.setArguments(args); QDBusMessage reply = conn.call(msg, QDBus::Block, 10*1000); QVERIFY(reply.type() == QDBusMessage::ReplyMessage); //check if backup file was created successfully QVERIFY(QFile::exists("/home/user/.signon/signondb.bin")); QFile::copy("/home/user/.signon/signondb.bin", "/home/user/.signon/signondb.bin2"); msg = QDBusMessage::createMethodCall(SIGNOND_SERVICE + ".Backup", SIGNOND_DAEMON_OBJECTPATH + "/Backup", "com.nokia.backupclient", "backupFinished"); reply = conn.call(msg, QDBus::Block, 10*1000); QVERIFY(reply.type() == QDBusMessage::ReplyMessage); QVERIFY(QFile::exists("/home/user/.signon/signondb.bin") == false); } void TestBackup::restoreTest() { QDBusConnection conn (SIGNOND_BUS); QVERIFY(QFile::exists("/home/user/.signon/signondb.bin2")); QFile::rename("/home/user/.signon/signondb.bin2", "/home/user/.signon/signondb.bin"); QDBusMessage msg = QDBusMessage::createMethodCall(SIGNOND_SERVICE + ".Backup", SIGNOND_DAEMON_OBJECTPATH + "/Backup", "com.nokia.backupclient", "restoreStarts"); QList args; msg.setArguments(args); QDBusMessage reply = conn.call(msg, QDBus::Block, 10*1000); QVERIFY(reply.type() == QDBusMessage::ReplyMessage); //check if backup file was created successfully msg = QDBusMessage::createMethodCall(SIGNOND_SERVICE + ".Backup", SIGNOND_DAEMON_OBJECTPATH + "/Backup", "com.nokia.backupclient", "restoreFinished"); reply = conn.call(msg, QDBus::Block, 10*1000); QVERIFY(QFile::exists("/home/user/.signon/signondb.bin") == false); QVERIFY(QFile::exists("/home/user/.signon/signon.db")); QVERIFY(reply.type() == QDBusMessage::ReplyMessage); } void TestBackup::backupNormalTest() { daemonProcess = new QProcess(); daemonProcess->start("signond"); daemonProcess->waitForStarted(10 * 1000); backupTest(); //check that daemon is still running normally after backup close signal QVERIFY(daemonProcess->state()==QProcess::Running); daemonProcess->kill(); daemonProcess->waitForFinished(); delete daemonProcess; daemonProcess = NULL; } void TestBackup::restoreNormalTest() { daemonProcess = new QProcess(); daemonProcess->start("signond"); daemonProcess->waitForStarted(10 * 1000); restoreTest(); //check that daemon is still running normally after backup close signal QVERIFY(daemonProcess->state()==QProcess::Running); daemonProcess->kill(); daemonProcess->waitForFinished(); delete daemonProcess; daemonProcess = NULL; } QTEST_MAIN(TestBackup) signond-nicolasfella/tests/signond-tests/backuptest.h0000664000175000017500000000252714615454535023346 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef BACKUPTEST_H_ #define BACKUPTEST_H_ #include #include #include "signond/signoncommon.h" using namespace SignOn; class TestBackup: public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); //backup mode void backupTest(); void restoreTest(); void backupNormalTest(); void restoreNormalTest(); private: QProcess *daemonProcess; }; #endif //BACKUPTEST_H_ signond-nicolasfella/tests/signond-tests/databasetest.h0000664000175000017500000000366614615454535023652 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef DATABASETEST_H_ #define DATABASETEST_H_ #include #include #include "signond/signoncommon.h" #include "credentialsdb.h" #include "default-secrets-storage.h" #include "signonidentityinfo.h" using namespace SignOn; using namespace SignonDaemonNS; class TestDatabase: public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); void createTableStructureTest(); void queryListTest(); void insertMethodsTest(); void methodsTest(); void checkPasswordTest(); void credentialsTest(); void insertCredentialsTest(); void updateCredentialsTest(); void removeCredentialsTest(); void clearTest(); void dataTest(); void referenceTest(); void cacheTest(); void accessControlListTest(); void credentialsOwnerSecurityTokenTest(); private: CredentialsDB *m_db; DefaultSecretsStorage *m_secretsStorage; MetaDataDB *m_meta; MethodMap testMethods; QStringList testRealms; QStringList testAcl; }; #endif //DATABASETEST_H_ signond-nicolasfella/tests/signond-tests/fake_signonui.h0000664000175000017500000000325714615454535024023 0ustar coucoufcoucouf/* * Copyright (C) 2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This file is part of signond * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SSO_FAKE_SIGNONUI_H #define SSO_FAKE_SIGNONUI_H #include #include class FakeSignOnUi { public: FakeSignOnUi(QtDBusMock::DBusMock *mock): m_mock(mock) { m_mock->registerTemplate("com.nokia.singlesignonui", SIGNONUI_MOCK_TEMPLATE, QDBusConnection::SessionBus); } void setNextReply(const QVariantMap &reply) { mockedService().call("SetNextReply", reply); } OrgFreedesktopDBusMockInterface &mockedService() { return m_mock->mockInterface("com.nokia.singlesignonui", "/SignonUi", "com.nokia.singlesignonui", QDBusConnection::SessionBus); } private: QtDBusMock::DBusMock *m_mock; }; #endif // SSO_FAKE_SIGNONUI_H signond-nicolasfella/tests/signond-tests/identity-tool.cpp0000664000175000017500000000367614615454535024346 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include using namespace SignOn; int main(int argc, char **argv) { QCoreApplication app(argc, argv); QTextStream out(stdout); IdentityInfo info; QStringList args = QCoreApplication::arguments(); for (int i = 1; i < args.count(); i++) { if (args[i] == "--acl") { info.setAccessControlList(args[++i].split(',')); } else if (args[i] == "--method") { QString method = args[++i]; QStringList mechanisms = args[++i].split(','); info.setMethod(method, mechanisms); } else if (args[i] == "--caption") { info.setCaption(args[++i]); } } Identity *identity = Identity::newIdentity(info); Q_ASSERT(identity != NULL); QObject::connect(identity, SIGNAL(error(const SignOn::Error&)), &app, SLOT(quit())); QObject::connect(identity, SIGNAL(credentialsStored(const quint32)), &app, SLOT(quit())); identity->storeCredentials(); app.exec(); Q_ASSERT(identity->id() != 0); out << identity->id(); return 0; } signond-nicolasfella/tests/signond-tests/include.cpp0000664000175000017500000000211714615454535023152 0ustar coucoufcoucouf/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef PLUGINPROXY_EXTERNAL_INCLUDED_ #define PLUGINPROXY_EXTERNAL_INCLUDED_ #include "pluginproxy.cpp" #include "blobiohandler.cpp" #endif //_EXTERNAL_INCLUDED_ signond-nicolasfella/tests/signond-tests/mock-ac-plugin/0000775000175000017500000000000014615454547023633 5ustar coucoufcoucoufsignond-nicolasfella/tests/signond-tests/mock-ac-plugin/access-control-manager.cpp0000664000175000017500000001170014615454535030662 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "access-control-manager.h" #include #include #include #include #include #include #include #ifdef ENABLE_P2P #include #endif static const char keychainAppId[] = "SignondKeychain"; class AccessReply: public SignOn::AccessReply { Q_OBJECT public: AccessReply(const SignOn::AccessRequest &request, const QString &appId, QObject *parent = 0); private Q_SLOTS: void onProcessFinished(); private: QProcess m_helper; }; AccessReply::AccessReply(const SignOn::AccessRequest &request, const QString &appId, QObject *parent): SignOn::AccessReply(request, parent) { /* Spawn the IDENTITY_AC_HELPER process, which will decide whether access * to the identity should be allowed (based on some fields found in the * identity itself), and will exit with code 1 if the access has been * allowed. */ QObject::connect(&m_helper, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(onProcessFinished())); m_helper.setProcessChannelMode(QProcess::ForwardedChannels); QStringList args; args << QString::number(request.identity()); args << appId; m_helper.start(IDENTITY_AC_HELPER, args); } void AccessReply::onProcessFinished() { qDebug() << Q_FUNC_INFO << m_helper.exitStatus() << m_helper.exitCode(); if (m_helper.exitStatus() == QProcess::NormalExit && m_helper.exitCode() == EXIT_SUCCESS) { accept(); } else { decline(); } } AccessControlManager::AccessControlManager(QObject *parent): SignOn::AbstractAccessControlManager(parent) { } AccessControlManager::~AccessControlManager() { } QString AccessControlManager::keychainWidgetAppId() { return QLatin1String(keychainAppId); } bool AccessControlManager::isPeerAllowedToAccess( const QDBusConnection &peerConnection, const QDBusMessage &peerMessage, const QString &securityContext) { QString appId = appIdOfPeer(peerConnection, peerMessage); if (appId == securityContext || appId == IDENTITY_AC_HELPER) { qDebug() << "Allowing"; return true; } else { qDebug() << "Blocking access"; return false; } } QString AccessControlManager::appIdOfPeer(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage) { pid_t pid = pidOfPeer(peerConnection, peerMessage); QFile file(QString::fromLatin1("/proc/%1/cmdline").arg(pid)); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Couldn't read name of pid" << pid; return QString::fromLatin1("pid-%1").arg(pid); } QByteArray command = file.readLine().split('\0').value(0, "unknown"); return QString::fromUtf8(command); } pid_t AccessControlManager::pidOfPeer(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage) { QString service = peerMessage.service(); if (service.isEmpty()) { #ifdef ENABLE_P2P DBusConnection *connection = (DBusConnection *)peerConnection.internalPointer(); unsigned long pid = 0; dbus_bool_t ok = dbus_connection_get_unix_process_id(connection, &pid); if (Q_UNLIKELY(!ok)) { qWarning() << "Couldn't get PID of caller!"; return 0; } return pid; #else qWarning() << "Empty caller name, and no P2P support enabled"; return 0; #endif } else { return peerConnection.interface()->servicePid(service).value(); } } SignOn::AccessReply * AccessControlManager::handleRequest(const SignOn::AccessRequest &request) { QString appId = appIdOfPeer(request.peerConnection(), request.peerMessage()); qDebug() << Q_FUNC_INFO << appId; return new AccessReply(request, appId, this); } #include "access-control-manager.moc" signond-nicolasfella/tests/signond-tests/mock-ac-plugin/access-control-manager.h0000664000175000017500000000334314615454535030333 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_MOCK_ACCESS_CONTROL_MANAGER_H #define SIGNON_MOCK_ACCESS_CONTROL_MANAGER_H #include #include class AccessControlManager: public SignOn::AbstractAccessControlManager { Q_OBJECT public: AccessControlManager(QObject *parent = 0); ~AccessControlManager(); bool isPeerAllowedToAccess(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage, const QString &securityContext); QString appIdOfPeer(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage); QString keychainWidgetAppId(); SignOn::AccessReply *handleRequest(const SignOn::AccessRequest &request); private: pid_t pidOfPeer(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage); }; #endif // SIGNON_MOCK_ACCESS_CONTROL_MANAGER_H signond-nicolasfella/tests/signond-tests/mock-ac-plugin/identity-ac-helper.cpp0000664000175000017500000000555614615454535030036 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include using namespace SignOn; class Helper: public QObject { Q_OBJECT public: Helper(quint32 id, const QString &appId); private Q_SLOTS: void onError(const SignOn::Error &error); void onInfo(const SignOn::IdentityInfo &info); void onCredentialsStored(); private: Identity *m_identity; QString m_appId; }; Helper::Helper(quint32 id, const QString &appId): QObject(), m_identity(0), m_appId(appId) { m_identity = Identity::existingIdentity(id); Q_ASSERT(m_identity != NULL); QObject::connect(m_identity, SIGNAL(info(const SignOn::IdentityInfo&)), this, SLOT(onInfo(const SignOn::IdentityInfo&))); QObject::connect(m_identity, SIGNAL(error(const SignOn::Error&)), this, SLOT(onError(const SignOn::Error&))); m_identity->queryInfo(); } void Helper::onInfo(const SignOn::IdentityInfo &info) { /* If the identity caption has the magic value of "allow", then update the * ACL and return true. */ bool isAllowed = (info.caption() == "allow"); if (!isAllowed) { QCoreApplication::exit(EXIT_FAILURE); return; } QObject::connect(m_identity, SIGNAL(credentialsStored(const quint32)), this, SLOT(onCredentialsStored())); IdentityInfo updated = info; updated.setAccessControlList(info.accessControlList() << m_appId); m_identity->storeCredentials(updated); } void Helper::onCredentialsStored() { qDebug() << Q_FUNC_INFO; QCoreApplication::exit(EXIT_SUCCESS); } void Helper::onError(const SignOn::Error &error) { qDebug() << Q_FUNC_INFO << error.type() << error.message(); QCoreApplication::exit(EXIT_FAILURE); } int main(int argc, char **argv) { QCoreApplication app(argc, argv); QStringList args = QCoreApplication::arguments(); uint id = args.at(1).toUInt(); QString appId = args.at(2); qDebug() << "Started" << id << appId; Helper helper(quint32(id), appId); return app.exec(); } #include "identity-ac-helper.moc" signond-nicolasfella/tests/signond-tests/mock-ac-plugin/mock-ac-plugin.pro0000664000175000017500000000011314615454535027153 0ustar coucoufcoucoufTEMPLATE = subdirs SUBDIRS = \ plugin.pro \ identity-ac-helper.pro signond-nicolasfella/tests/signond-tests/mock-ac-plugin/plugin.cpp0000664000175000017500000000224514615454535025635 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "plugin.h" #include "access-control-manager.h" #include using namespace SignOn; Plugin::Plugin(QObject *parent): QObject(parent) { setObjectName(QLatin1String("mock-ac")); } AbstractAccessControlManager * Plugin::accessControlManager(QObject *parent) const { qDebug() << Q_FUNC_INFO; return new AccessControlManager(parent); } signond-nicolasfella/tests/signond-tests/mock-ac-plugin/plugin.h0000664000175000017500000000244714615454535025306 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef SIGNON_MOCK_PLUGIN_H #define SIGNON_MOCK_PLUGIN_H #include #include class Plugin: public QObject, public SignOn::ExtensionInterface3 { Q_OBJECT Q_INTERFACES(SignOn::ExtensionInterface3) Q_PLUGIN_METADATA(IID "com.nokia.SingleSignOn.ExtensionInterface/3.0") public: Plugin(QObject *parent = 0); SignOn::AbstractAccessControlManager * accessControlManager(QObject *parent = 0) const; }; #endif // SIGNON_MOCK_PLUGIN_H signond-nicolasfella/tests/signond-tests/mock-ac-plugin/plugin.pro0000664000175000017500000000125314615454535025651 0ustar coucoufcoucoufinclude(../../tests.pri) TEMPLATE = lib TARGET = signon-mock-ac CONFIG += \ link_pkgconfig \ plugin \ qt QT += \ core \ dbus QT -= gui DEFINES += \ IDENTITY_AC_HELPER=\\\"$${TOP_BUILD_DIR}/tests/signond-tests/mock-ac-plugin/identity-ac-helper\\\" CONFIG(enable-p2p) { DEFINES += ENABLE_P2P PKGCONFIG += dbus-1 } QMAKE_CXXFLAGS += \ -fvisibility=hidden LIBS += -lsignon-extension INCLUDEPATH += . \ $$TOP_SRC_DIR/lib/signond QMAKE_LIBDIR += \ $${TOP_BUILD_DIR}/lib/signond/SignOn QMAKE_RPATHDIR = $${QMAKE_LIBDIR} HEADERS = \ access-control-manager.h \ plugin.h SOURCES = \ access-control-manager.cpp \ plugin.cpp signond-nicolasfella/tests/signond-tests/mock-ac-plugin/signond.conf0000664000175000017500000000166114615454535026144 0ustar coucoufcoucouf;Signon Daemon configuration file [General] ; Uncomment the StoragePath line to specify a location for the signon DB. ; If not given, uses $XDG_CONFIG_HOME/signond (or ~/.config/signond if ; the variable XDG_CONFIG_HOME is unset). ;StoragePath=~/.signon/ ;0 - fatal, 1 - critical (default), 2 - info/debug LoggingLevel=2 [SecureStorage] ; CryptoManager selects the encryption for the credentials FS. Possible values: ; "default" - no encryption ; "cryptsetup" - encrypted with the cryptsetup extension CryptoManager=default ; AccessControlManager selects the type of AC framework Possible values: ; "default" - no AC ; "smack-ac" - Smack AC ; "mssf-ac" - MSSF AC AccessControlManager=mock-ac FileSystemName=signonfs Size=8 FileSystemType=ext2 SecretsStorage=default [ObjectTimeouts] ; All the values are in seconds IdentityTimeout=30 AuthSessionTimeout=30 ; Set the timeout to 0 to disable quitting due to inactivity DaemonTimeout=5 signond-nicolasfella/tests/signond-tests/mock-ac-plugin/identity-ac-helper.pro0000664000175000017500000000055214615454547030046 0ustar coucoufcoucoufinclude(../../../common-project-config.pri) TEMPLATE = app TARGET = identity-ac-helper QT += core QT -= gui LIBS += -lsignon-qt$${QT_MAJOR_VERSION} QMAKE_LIBDIR += \ $${TOP_BUILD_DIR}/lib/signond/SignOn \ $${TOP_BUILD_DIR}/lib/SignOn QMAKE_RPATHDIR = $${QMAKE_LIBDIR} INCLUDEPATH += \ $${TOP_SRC_DIR}/lib SOURCES = \ identity-ac-helper.cpp signond-nicolasfella/tests/signond-tests/session_tool.cpp0000664000175000017500000000661614615454535024257 0ustar coucoufcoucouf/* * This file is part of signond * * Copyright (C) 2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include #include "signond/signoncommon.h" class AuthSession: public QObject { Q_OBJECT public: AuthSession(const QString &path); ~AuthSession(); public Q_SLOTS: void process(const QVariantMap &sessionData); void onResponse(const QVariantMap &response); void onError(const QDBusError &error); private: QTextStream m_out; QDBusInterface *m_dbus; }; AuthSession::AuthSession(const QString &path): QObject(), m_out(stdout) { m_dbus = new QDBusInterface(SIGNOND_SERVICE, path, QLatin1String(SIGNOND_AUTH_SESSION_INTERFACE), QDBusConnection::sessionBus()); } AuthSession::~AuthSession() { delete m_dbus; } void AuthSession::process(const QVariantMap &sessionData) { QVariantList arguments; arguments += sessionData; arguments += QStringLiteral("mech1"); QDBusMessage msg = QDBusMessage::createMethodCall(m_dbus->service(), m_dbus->path(), m_dbus->interface(), QStringLiteral("process")); msg.setArguments(arguments); m_dbus->connection().callWithCallback(msg, this, SLOT(onResponse(const QVariantMap&)), SLOT(onError(const QDBusError&)), SIGNOND_MAX_TIMEOUT); } void AuthSession::onResponse(const QVariantMap &response) { // The called doesn't really care about the response value Q_UNUSED(response); m_out << "Response:"; QCoreApplication::quit(); } void AuthSession::onError(const QDBusError &error) { m_out << "Error:" << error.name(); QCoreApplication::quit(); } int main(int argc, char **argv) { QCoreApplication app(argc, argv); QString sessionPath; QStringList args = QCoreApplication::arguments(); for (int i = 1; i < args.count(); i++) { if (args[i] == "--sessionPath") { sessionPath = args[++i]; } } AuthSession authSession(sessionPath); QVariantMap sessionData { { "Secret", QStringLiteral("testSecret") }, { "UserName", QStringLiteral("testUsername") }, }; authSession.process(sessionData); QTimer::singleShot(10*1000, &app, SLOT(quit())); app.exec(); return 0; } #include "session_tool.moc" signond-nicolasfella/tests/signond-tests/session_tool.pro0000664000175000017500000000026614615454535024270 0ustar coucoufcoucoufinclude(../../common-project-config.pri) TEMPLATE = app TARGET = session_tool QT += core dbus QT -= gui INCLUDEPATH += \ $${TOP_SRC_DIR}/lib SOURCES = \ session_tool.cpp signond-nicolasfella/tests/signond-tests/signond-tests.pro0000664000175000017500000000063314615454535024347 0ustar coucoufcoucoufTEMPLATE = subdirs CONFIG += ordered SUBDIRS = \ tst_access_control_manager_helper.pro \ tst_timeouts.pro \ tst_pluginproxy.pro \ tst_database.pro \ access-control.pro \ system($$pkgConfigExecutable() --exists libqtdbusmock-1) { SUBDIRS += \ session_tool.pro \ tst_signond.pro tst_signond.depends += session_tool } # Disabled until fixed #SUBDIRS += tst_backup.pro signond-nicolasfella/tests/signond-tests/signonui.py0000664000175000017500000000326314615454535023233 0ustar coucoufcoucouf'''signonui mock template This creates the expected methods and properties of the com.nokia.singlesignonui service. ''' # This program 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; either version 2.1 of the License. See # http://www.gnu.org/copyleft/lgpl.html for the full text of the license. __author__ = 'Alberto Mardegan' __email__ = 'alberto.mardegan@canonical.com' __copyright__ = '(c) 2016 Canonical Ltd.' __license__ = 'LGPL 2.1' import dbus import time from dbusmock import MOCK_IFACE import dbusmock BUS_NAME = 'com.nokia.singlesignonui' MAIN_OBJ = '/SignonUi' MAIN_SERVICE_IFACE = 'com.nokia.singlesignonui' MAIN_IFACE = MAIN_SERVICE_IFACE SYSTEM_BUS = False def query_dialog(self, params): if self.nextReplyError: raise dbus.exceptions.DBusException('SignOnUi error', name=self.nextReplyError) return self.nextReplyData def load(mock, parameters): mock.query_dialog = query_dialog mock.refresh_dialog = query_dialog mock.AddMethods(MAIN_SERVICE_IFACE, [ ('queryDialog', 'a{sv}', 'a{sv}', 'ret = self.query_dialog(self, args[0])'), ('refreshDialog', 'a{sv}', 'a{sv}', 'ret = self.refresh_dialog(self, args[0])'), ('cancelUiRequest', 's', '', 'ret = None'), ('removeIdentityData', 'u', '', 'ret = None'), ]) mock.nextReplyData = {} mock.nextReplyError = '' @dbus.service.method(MOCK_IFACE, in_signature='a{sv}', out_signature='') def SetNextReply(self, data): self.nextReplyData = data.get('data', {}) self.nextReplyError = data.get('error', '') signond-nicolasfella/tests/signond-tests/testpluginproxy.cpp0000664000175000017500000002031414615454535025026 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include "testpluginproxy.h" #include #include #include void TestPluginProxy::initTestCase() { m_proxy = NULL; #ifndef NO_SIGNON_USER QVERIFY2(!::getuid(), "test must be run as root"); //check signon user struct passwd *signonUser = getpwnam("signon"); QVERIFY2(signonUser, "signon user do not exist, add with 'useradd --system signon'"); #endif qRegisterMetaType("QVariantMap"); } void TestPluginProxy::cleanupTestCase() { delete m_proxy; } void TestPluginProxy::create_nonexisting() { PluginProxy *pp = PluginProxy::createNewPluginProxy("nonexisting"); QVERIFY(pp == NULL); } void TestPluginProxy::create_dummy() { PluginProxy *pp = PluginProxy::createNewPluginProxy("ssotest"); QVERIFY(pp != NULL); m_proxy = pp; } void TestPluginProxy::type_for_dummy() { QString type = m_proxy->type(); QVERIFY(type == "ssotest"); } void TestPluginProxy::mechanisms_for_dummy() { QStringList mechs = m_proxy->mechanisms(); QStringList pattern; pattern << "mech1"; pattern << "mech2"; pattern << "mech3"; pattern << "BLOB"; QVERIFY(mechs == pattern); } void TestPluginProxy::process_for_dummy() { // Build up the session data. It will include a value // which is itself a QVariantMap in order to test the // dbus argument expansion during marshalling. QVariantMap providedTokens; providedTokens.insert("AccessToken", "12345"); providedTokens.insert("RefreshToken", "abcde"); QVariantMap complexInData; complexInData.insert("ProvidedTokens", providedTokens); SessionData inData(complexInData); inData.setRealm("testRealm"); inData.setUserName("testUsername"); QVariantMap inDataV; foreach(QString key, inData.propertyNames()) inDataV[key] = inData.getProperty(key); QSignalSpy spyResult(m_proxy, SIGNAL(processResultReply(const QVariantMap&))); QSignalSpy spyState(m_proxy, SIGNAL(stateChanged(int, const QString&))); QEventLoop loop; QObject::connect(m_proxy, SIGNAL(processResultReply(const QVariantMap&)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); QString cancelKey = QUuid::createUuid().toString(); bool res = m_proxy->process(inDataV, "mech1"); QVERIFY(res); loop.exec(); QCOMPARE(spyResult.count(), 1); QCOMPARE(spyState.count(), 10); QVariantMap outData = spyResult.at(0).at(0).toMap(); qDebug() << outData; QVERIFY(outData.contains("UserName") && outData["UserName"] == "testUsername"); QVERIFY(outData.contains("Realm") && outData["Realm"] == "testRealm_after_test"); QVERIFY(outData.contains("ProvidedTokens") && outData["ProvidedTokens"] == providedTokens); } void TestPluginProxy::processUi_for_dummy() { SessionData inData; inData.setRealm("testRealm"); inData.setUserName("testUsername"); inData.setUiPolicy(NoUserInteractionPolicy); QVariantMap inDataV; foreach(QString key, inData.propertyNames()) inDataV[key] = inData.getProperty(key); QSignalSpy spyResult(m_proxy, SIGNAL(processResultReply(const QVariantMap&))); QSignalSpy spyError(m_proxy, SIGNAL(processError(int, const QString&))); QSignalSpy spyUi(m_proxy, SIGNAL(processUiRequest(const QVariantMap&))); QEventLoop loop; QObject::connect(m_proxy, SIGNAL(processResultReply(const QVariantMap&)), &loop, SLOT(quit())); QObject::connect(m_proxy, SIGNAL(processError(int, const QString&)), &loop, SLOT(quit())); QObject::connect(m_proxy, SIGNAL(processUiRequest(const QVariantMap&)), &loop, SLOT(quit())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); QString cancelKey = QUuid::createUuid().toString(); bool res = m_proxy->process(inDataV, "mech2"); QVERIFY(res); loop.exec(); QCOMPARE(spyUi.count(), 0); QCOMPARE(spyError.count(), 1); int err = spyError.at(0).at(0).toInt(); QString errMsg = spyError.at(0).at(1).toString(); qDebug() << err; qDebug() << errMsg; QVERIFY(err == Error::NotAuthorized); inDataV["UiPolicy"] = 0; res = m_proxy->process(inDataV, "mech2"); QVERIFY(res); loop.exec(); QCOMPARE(spyUi.count(), 1); } void TestPluginProxy::process_and_cancel_for_dummy() { SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); QVariantMap inDataV; foreach(QString key, inData.propertyNames()) inDataV[key] = inData.getProperty(key); QSignalSpy spyResult(m_proxy, SIGNAL(processResultReply(const QVariantMap&))); QSignalSpy spyError(m_proxy, SIGNAL(processError(int, const QString&))); QEventLoop loop; QObject::connect(m_proxy, SIGNAL(processResultReply(const QVariantMap&)), &loop, SLOT(quit())); QObject::connect(m_proxy, SIGNAL(processError(int, const QString&)), &loop, SLOT(quit())); QTimer::singleShot(0.2*1000, m_proxy, SLOT(cancel())); QTimer::singleShot(10*1000, &loop, SLOT(quit())); bool res = m_proxy->process(inDataV, "mech1"); QVERIFY(res); loop.exec(); QCOMPARE(spyResult.count(), 0); QCOMPARE(spyError.count(), 1); int err = spyError.at(0).at(0).toInt(); QString errMsg = spyError.at(0).at(1).toString(); qDebug() << err; qDebug() << errMsg; QVERIFY(err == Error::SessionCanceled); QVERIFY(errMsg == QString("The operation is canceled")); } void TestPluginProxy::process_wrong_mech_for_dummy() { SessionData inData; inData.setSecret("testSecret"); inData.setUserName("testUsername"); QVariantMap inDataV; foreach(QString key, inData.propertyNames()) inDataV[key] = inData.getProperty(key); QSignalSpy spyResult(m_proxy, SIGNAL(processResultReply(const QVariantMap&))); QSignalSpy spyError(m_proxy, SIGNAL(processError(int, const QString&))); QEventLoop loop; QObject::connect(m_proxy, SIGNAL(processResultReply(const QVariantMap&)), &loop, SLOT(quit())); QObject::connect(m_proxy, SIGNAL(processError(int, const QString&)), &loop, SLOT(quit())); bool res = m_proxy->process(inDataV, "wrong"); QVERIFY(res); loop.exec(); QCOMPARE(spyResult.count(), 0); QCOMPARE(spyError.count(), 1); int err = spyError.at(0).at(0).toInt(); QString errMsg = spyError.at(0).at(1).toString(); qDebug() << err << " " << errMsg; QVERIFY(err == Error::MechanismNotAvailable); QVERIFY(errMsg == QString("The given mechanism is unavailable")); } void TestPluginProxy::wrong_user_for_dummy() { if (::getuid()) { QSKIP("This test need to be run as root", SkipSingle); } #ifndef NO_SIGNON_USER QProcess *pluginProcess = new QProcess(this); QVERIFY(pluginProcess->execute(QString("/usr/bin/signonpluginprocess"))==2); #endif } #if !defined(SSO_CI_TESTMANAGEMENT) QTEST_MAIN(TestPluginProxy) #endif signond-nicolasfella/tests/signond-tests/testpluginproxy.h0000664000175000017500000000314514615454535024476 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef TESTPLUGINPROXY_H_ #define TESTPLUGINPROXY_H_ #include #include #include "signond/signoncommon.h" #include "SignOn/sessiondata.h" #include "SignOn/authpluginif.h" #include "pluginproxy.h" using namespace SignonDaemonNS; using namespace SignOn; class TestPluginProxy: public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void create_nonexisting(); void create_dummy(); void type_for_dummy(); void mechanisms_for_dummy(); void process_for_dummy(); void processUi_for_dummy(); void process_wrong_mech_for_dummy(); void process_and_cancel_for_dummy(); void wrong_user_for_dummy(); private: PluginProxy *m_proxy; }; #endif //TESTPLUGINPROXY_H_ signond-nicolasfella/tests/signond-tests/timeouts.cpp0000664000175000017500000001770014615454535023404 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "timeouts.h" #include #include #include #include #include "signond/signoncommon.h" using namespace SignOn; /* * test timeout 20 seconds * */ #define test_timeout 20000 void TimeoutsTest::initTestCase() { } void TimeoutsTest::cleanupTestCase() { } void TimeoutsTest::init() { completed = false; } void TimeoutsTest::identityTimeout() { QEventLoop loop; QTimer::singleShot(test_timeout, &loop, SLOT(quit())); QObject::connect(this, SIGNAL(finished()), &loop, SLOT(quit()), Qt::QueuedConnection); QMap methods; methods.insert("dummy", QStringList() << "mech1" << "mech2"); IdentityInfo info = IdentityInfo(QLatin1String("timeout test"), QLatin1String("timeout@test"), methods); info.setAccessControlList(QStringList() << "*"); Identity *identity = Identity::newIdentity(info); QVERIFY(identity != NULL); QObject::connect(identity, SIGNAL(credentialsStored(const quint32)), this, SLOT(credentialsStored(const quint32))); QObject::connect(identity, SIGNAL(error(const SignOn::Error&)), this, SLOT(identityError(const SignOn::Error&))); identity->storeCredentials(); loop.exec(); QVERIFY(identity->id() != SSO_NEW_IDENTITY); QDBusConnection conn = SIGNOND_BUS; QDBusMessage msg = QDBusMessage::createMethodCall(SIGNOND_SERVICE, SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getIdentity"); QList args; args << identity->id(); args << QString("application_security_context"); msg.setArguments(args); QDBusMessage reply = conn.call(msg); QCOMPARE(reply.type(), QDBusMessage::ReplyMessage); QDBusObjectPath objectPath = reply.arguments()[0].value(); QString path = objectPath.path(); qDebug() << "Got path" << path; QVERIFY(!path.isEmpty()); bool success; QTest::qSleep(100); success = triggerDisposableCleanup(); QVERIFY(success); /* The identity object must exist now */ QVERIFY(identityAlive(path)); QTest::qSleep(6 * 1000); success = triggerDisposableCleanup(); QVERIFY(success); /* After SSO_IDENTITY_TIMEOUT seconds, the identity must have been * destroyed */ QVERIFY(!identityAlive(path)); /* Calling a method on the client should re-register the identity */ QSignalSpy removed(identity, SIGNAL(removed())); QObject::connect(identity, SIGNAL(removed()), &loop, SLOT(quit()), Qt::QueuedConnection); identity->remove(); loop.exec(); QCOMPARE(removed.count(), 1); } void TimeoutsTest::identityRegisterTwice() { QEventLoop loop; QTimer::singleShot(test_timeout, &loop, SLOT(quit())); QObject::connect(this, SIGNAL(finished()), &loop, SLOT(quit()), Qt::QueuedConnection); QMap methods; methods.insert("dummy", QStringList() << "mech1" << "mech2"); IdentityInfo info = IdentityInfo(QLatin1String("timeout test"), QLatin1String("timeout@test"), methods); info.setAccessControlList(QStringList() << "*"); Identity *identity = Identity::newIdentity(info); QVERIFY(identity != NULL); QObject::connect(identity, SIGNAL(credentialsStored(const quint32)), this, SLOT(credentialsStored(const quint32))); QObject::connect(identity, SIGNAL(error(const SignOn::Error &)), this, SLOT(identityError(const SignOn::Error &))); identity->storeCredentials(); loop.exec(); QVERIFY(identity->id() != SSO_NEW_IDENTITY); QDBusConnection conn = SIGNOND_BUS; QDBusMessage msg = QDBusMessage::createMethodCall(SIGNOND_SERVICE, SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getIdentity"); QList args; args << identity->id(); args << QString("application_security_context"); msg.setArguments(args); QDBusMessage reply = conn.call(msg); QCOMPARE(reply.type(), QDBusMessage::ReplyMessage); QDBusObjectPath objectPath = reply.arguments()[0].value(); QString path = objectPath.path(); qDebug() << "Got path" << path; QVERIFY(!path.isEmpty()); bool success; QTest::qSleep(100); success = triggerDisposableCleanup(); QVERIFY(success); /* The identity object must exist now */ QVERIFY(identityAlive(path)); QTest::qSleep(6 * 1000); /* now we register the same identity again. The expected behavior is that * the registration succeeds, possibly returning the same object path as * before. * This is to test a regression (NB#182914) which was happening because * signond was deleting the expired Identity immediately after returning * its object path to the client. */ reply = conn.call(msg); QVERIFY(reply.type() == QDBusMessage::ReplyMessage); objectPath = reply.arguments()[0].value(); path = objectPath.path(); qDebug() << "Got path" << path; QVERIFY(!path.isEmpty()); QVERIFY(identityAlive(path)); } void TimeoutsTest::identityError(const SignOn::Error &error) { qDebug() << Q_FUNC_INFO << error.message(); QFAIL("Unexpected error!"); emit finished(); } bool TimeoutsTest::triggerDisposableCleanup() { QDBusConnection conn = SIGNOND_BUS; /* create a new identity just to trigger the cleanup of disposable * objects */ QDBusMessage msg = QDBusMessage::createMethodCall(SIGNOND_SERVICE, SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "registerNewIdentity"); msg << QString("application_security_context"); QDBusMessage reply = conn.call(msg); return (reply.type() == QDBusMessage::ReplyMessage); } bool TimeoutsTest::identityAlive(const QString &path) { QDBusConnection conn = SIGNOND_BUS; QString interface = QLatin1String("com.google.code.AccountsSSO.SingleSignOn.Identity"); QDBusMessage msg = QDBusMessage::createMethodCall(SIGNOND_SERVICE, path, interface, "getInfo"); QDBusMessage reply = conn.call(msg); return (reply.type() == QDBusMessage::ReplyMessage); } void TimeoutsTest::credentialsStored(const quint32 id) { QVERIFY(id != 0); emit finished(); } QTEST_MAIN(TimeoutsTest) signond-nicolasfella/tests/signond-tests/timeouts.h0000664000175000017500000000273714615454535023055 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #ifndef TIMEOUTS_TEST_H #define TIMEOUTS_TEST_H #include "SignOn/identity.h" #include #include using namespace SignOn; class TimeoutsTest: public QObject { Q_OBJECT public Q_SLOTS: void credentialsStored(const quint32 id); void identityError(const SignOn::Error &error); private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void init(); void identityTimeout(); void identityRegisterTwice(); signals: void finished(); private: bool triggerDisposableCleanup(); bool identityAlive(const QString &path); bool completed; }; #endif // TIMEOUTS_TEST_H signond-nicolasfella/tests/signond-tests/tst_access_control.cpp0000664000175000017500000002062614615454535025427 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2013-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #define IDENTITY_TOOL "./identity-tool" using namespace SignOn; namespace SignOnTests { class AccessControlTest: public QObject { Q_OBJECT public Q_SLOTS: void onInfo(const SignOn::IdentityInfo &info); private Q_SLOTS: void testOwner(); void testAccessDenied(); void testAccessDeniedSession(); void testAccessAllowed(); void testAccessRequestAllowed(); void testAccessRequestAllowedSession(); private: IdentityInfo m_info; }; } // namespace using namespace SignOnTests; void AccessControlTest::onInfo(const SignOn::IdentityInfo &info) { qDebug() << "Owner:" < methods; methods.insert("dummy", QStringList() << "mech1" << "mech2"); IdentityInfo info = IdentityInfo(QLatin1String("ac test"), QLatin1String("ac@test"), methods); Identity *identity = Identity::newIdentity(info, this); QVERIFY(identity != NULL); QObject::connect(identity, SIGNAL(error(const SignOn::Error&)), &loop, SLOT(quit())); QObject::connect(identity, SIGNAL(credentialsStored(const quint32)), &loop, SLOT(quit())); identity->storeCredentials(); loop.exec(); QVERIFY(identity->id() != 0); QObject::connect(identity, SIGNAL(info(const SignOn::IdentityInfo&)), this, SLOT(onInfo(const SignOn::IdentityInfo&))); QObject::connect(identity, SIGNAL(info(const SignOn::IdentityInfo&)), &loop, SLOT(quit())); identity->queryInfo(); loop.exec(); QCOMPARE(m_info.owner(), QCoreApplication::arguments().at(0)); delete identity; } void AccessControlTest::testAccessDenied() { /* Create an identity from another process */ QProcess identityTool; identityTool.start(IDENTITY_TOOL, QStringList() << "--caption" << "no-acl"); QVERIFY(identityTool.waitForFinished()); uint id = identityTool.readAll().toUInt(); qDebug() << "Identity was created:" << id; Identity *identity = Identity::existingIdentity(id); QVERIFY(identity != NULL); QEventLoop loop; QSignalSpy infoSpy(identity, SIGNAL(info(const SignOn::IdentityInfo&))); QSignalSpy errorSpy(identity, SIGNAL(error(const SignOn::Error&))); QObject::connect(identity, SIGNAL(error(const SignOn::Error&)), &loop, SLOT(quit())); QObject::connect(identity, SIGNAL(info(const SignOn::IdentityInfo&)), &loop, SLOT(quit())); identity->queryInfo(); loop.exec(); QCOMPARE(infoSpy.count(), 0); QCOMPARE(errorSpy.count(), 1); SignOn::Error error = errorSpy.at(0).at(0).value(); QCOMPARE(error.type(), int(SignOn::Error::PermissionDenied)); delete identity; } void AccessControlTest::testAccessDeniedSession() { /* Create an identity from another process */ QProcess identityTool; identityTool.start(IDENTITY_TOOL, QStringList() << "--caption" << "no-acl"); QVERIFY(identityTool.waitForFinished()); uint id = identityTool.readAll().toUInt(); qDebug() << "Identity was created:" << id; AuthSession *session = new AuthSession(id, "dummy"); QVERIFY(session != NULL); QEventLoop loop; QSignalSpy errorSpy(session, SIGNAL(error(const SignOn::Error&))); QObject::connect(session, SIGNAL(error(const SignOn::Error&)), &loop, SLOT(quit())); session->process(SessionData()); loop.exec(); QCOMPARE(errorSpy.count(), 1); SignOn::Error error = errorSpy.at(0).at(0).value(); QCOMPARE(error.type(), int(SignOn::Error::PermissionDenied)); delete session; } void AccessControlTest::testAccessAllowed() { /* Create an identity from another process */ QProcess identityTool; identityTool.start(IDENTITY_TOOL, QStringList() << "--caption" << "with-acl" << "--acl" << QCoreApplication::arguments().at(0)); QVERIFY(identityTool.waitForFinished()); uint id = identityTool.readAll().toUInt(); qDebug() << "Identity was created:" << id; Identity *identity = Identity::existingIdentity(id); QVERIFY(identity != NULL); QEventLoop loop; QSignalSpy infoSpy(identity, SIGNAL(info(const SignOn::IdentityInfo&))); QSignalSpy errorSpy(identity, SIGNAL(error(const SignOn::Error&))); QObject::connect(identity, SIGNAL(error(const SignOn::Error&)), &loop, SLOT(quit())); QObject::connect(identity, SIGNAL(info(const SignOn::IdentityInfo&)), &loop, SLOT(quit())); identity->queryInfo(); loop.exec(); QCOMPARE(infoSpy.count(), 1); QCOMPARE(errorSpy.count(), 0); delete identity; } void AccessControlTest::testAccessRequestAllowed() { /* Create an identity from another process; use the "allow" caption to tell * the mock-ac-plugin to allow requests to this identity. */ QProcess identityTool; identityTool.start(IDENTITY_TOOL, QStringList() << "--caption" << "allow"); QVERIFY(identityTool.waitForFinished()); uint id = identityTool.readAll().toUInt(); qDebug() << "Identity was created:" << id; Identity *identity = Identity::existingIdentity(id); QVERIFY(identity != NULL); QEventLoop loop; QSignalSpy infoSpy(identity, SIGNAL(info(const SignOn::IdentityInfo&))); QSignalSpy errorSpy(identity, SIGNAL(error(const SignOn::Error&))); QObject::connect(identity, SIGNAL(error(const SignOn::Error&)), &loop, SLOT(quit())); QObject::connect(identity, SIGNAL(info(const SignOn::IdentityInfo&)), &loop, SLOT(quit())); identity->queryInfo(); loop.exec(); QCOMPARE(infoSpy.count(), 1); QCOMPARE(errorSpy.count(), 0); /* Verify that our process has been added to the ACL (by the * mock-ac-plugin, after seeing our special caption). */ SignOn::IdentityInfo info = infoSpy.at(0).at(0).value(); QCOMPARE(info.caption(), QLatin1String("allow")); QCOMPARE(info.accessControlList(), QStringList() << QCoreApplication::arguments().at(0)); delete identity; } void AccessControlTest::testAccessRequestAllowedSession() { /* Create an identity from another process; use the "allow" caption to tell * the mock-ac-plugin to allow requests to this identity. */ QProcess identityTool; identityTool.start(IDENTITY_TOOL, QStringList() << "--caption" << "allow"); QVERIFY(identityTool.waitForFinished()); uint id = identityTool.readAll().toUInt(); qDebug() << "Identity was created:" << id; AuthSession *session = new AuthSession(id, "dummy"); QVERIFY(session != NULL); QEventLoop loop; QSignalSpy errorSpy(session, SIGNAL(error(const SignOn::Error&))); QObject::connect(session, SIGNAL(error(const SignOn::Error&)), &loop, SLOT(quit())); session->process(SessionData()); loop.exec(); QCOMPARE(errorSpy.count(), 1); /* The error should be about the unknown "dummy" method, and not a * permission denied */ SignOn::Error error = errorSpy.at(0).at(0).value(); QCOMPARE(error.type(), int(SignOn::Error::MethodNotAvailable)); delete session; } QTEST_MAIN(AccessControlTest) #include "tst_access_control.moc" signond-nicolasfella/tests/signond-tests/tst_access_control.pro0000664000175000017500000000052414615454535025440 0ustar coucoufcoucoufTARGET = tst_access_control include(signond-tests.pri) SOURCES = \ tst_access_control.cpp check.commands = "SSO_PLUGINS_DIR=$${TOP_BUILD_DIR}/src/plugins/test SSO_EXTENSIONS_DIR=$${TOP_BUILD_DIR}/tests/signond-tests/mock-ac-plugin SSO_CONFIG_FILE_DIR=$${TOP_SRC_DIR}/tests/signond-tests/mock-ac-plugin $$RUN_WITH_SIGNOND ./$$TARGET" signond-nicolasfella/tests/signond-tests/tst_access_control_manager_helper.cpp0000664000175000017500000002154514615454535030461 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2014-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include #include "accesscontrolmanagerhelper.h" #include "credentialsaccessmanager.h" #include "credentialsdb.h" using namespace SignOn; using namespace SignonDaemonNS; // mock AbstractAccessControlManager { class AcmPlugin: public SignOn::AbstractAccessControlManager { Q_OBJECT public: AcmPlugin(QObject *parent = 0): SignOn::AbstractAccessControlManager(parent) {} ~AcmPlugin() {} bool isPeerAllowedToAccess(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage, const QString &securityContext) { QStringList appPermissions = m_permissions.value(appIdOfPeer(peerConnection, peerMessage)); return appPermissions.contains(securityContext); } QString appIdOfPeer(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage) { Q_UNUSED(peerConnection); return peerMessage.service(); } QString keychainWidgetAppId() { return m_keychainWidgetAppId; } SignOn::AccessReply *handleRequest(const SignOn::AccessRequest &request) { Q_UNUSED(request); return 0; } private: friend class AccessControlManagerHelperTest; QMap m_permissions; QString m_keychainWidgetAppId; }; // } mock AbstractAccessControlManager class AccessControlManagerHelperTest: public QObject { Q_OBJECT public: AccessControlManagerHelperTest(); private Q_SLOTS: void init(); void testOwnership_data(); void testOwnership(); void testIdentityAccess_data(); void testIdentityAccess(); public: static AccessControlManagerHelperTest *instance() { return m_instance; } SignonDaemonNS::CredentialsDB *credentialsDB() { return &m_db; } private: void setDbOwners(const QStringList &owners) { if (owners.contains("db-error")) { m_dbOwners = QStringList(); m_dbLastError = CredentialsDBError("DB error!", CredentialsDBError::ConnectionError); } else { m_dbOwners = owners; } } void setDbAcl(const QStringList &acl) { if (acl.contains("db-error")) { m_dbAcl = QStringList(); m_dbLastError = CredentialsDBError("DB error!", CredentialsDBError::ConnectionError); } else { m_dbAcl = acl; } } private: friend class SignonDaemonNS::CredentialsDB; static AccessControlManagerHelperTest *m_instance; AcmPlugin m_acmPlugin; SignonDaemonNS::CredentialsDB m_db; SignOn::CredentialsDBError m_dbLastError; QStringList m_dbAcl; QStringList m_dbOwners; QDBusConnection m_conn; }; AccessControlManagerHelperTest *AccessControlManagerHelperTest::m_instance = 0; namespace SignonDaemonNS { // mock CredentialsDB { CredentialsDB::CredentialsDB(const QString &metaDataDbName, SignOn::AbstractSecretsStorage *secretsStorage): QObject() { Q_UNUSED(metaDataDbName); Q_UNUSED(secretsStorage); } CredentialsDB::~CredentialsDB() { } SignOn::CredentialsDBError CredentialsDB::lastError() const { return AccessControlManagerHelperTest::instance()->m_dbLastError; } QStringList CredentialsDB::accessControlList(const quint32 identityId) { Q_UNUSED(identityId); return AccessControlManagerHelperTest::instance()->m_dbAcl; } QStringList CredentialsDB::ownerList(const quint32 identityId) { Q_UNUSED(identityId); return AccessControlManagerHelperTest::instance()->m_dbOwners; } // } mock CredentialsDB // mock CredentialsAccessManager { CredentialsDB *CredentialsAccessManager::credentialsDB() const { return AccessControlManagerHelperTest::instance()->credentialsDB(); } CredentialsAccessManager *CredentialsAccessManager::instance() { return 0; } } // namespace // } mock CredentialsAccessManager AccessControlManagerHelperTest::AccessControlManagerHelperTest(): QObject(), m_db(QString(), 0), m_conn(QLatin1String("test-connection")) { m_instance = this; } void AccessControlManagerHelperTest::init() { m_dbOwners = QStringList(); m_dbAcl = QStringList(); m_dbLastError = CredentialsDBError(); } void AccessControlManagerHelperTest::testOwnership_data() { QTest::addColumn("peer"); QTest::addColumn("ownerList"); QTest::addColumn("expectedOwnership"); QTest::newRow("DB error") << "tom" << (QStringList() << "db-error") << int(AccessControlManagerHelper::ApplicationIsNotOwner); QTest::newRow("empty") << "tom" << QStringList() << int(AccessControlManagerHelper::IdentityDoesNotHaveOwner); QTest::newRow("is only owner") << "tom" << (QStringList() << "tom") << int(AccessControlManagerHelper::ApplicationIsOwner); QTest::newRow("is co-owner") << "tom" << (QStringList() << "Bob" << "tom" << "harry") << int(AccessControlManagerHelper::ApplicationIsOwner); } void AccessControlManagerHelperTest::testOwnership() { QFETCH(QString, peer); QFETCH(QStringList, ownerList); QFETCH(int, expectedOwnership); setDbOwners(ownerList); m_acmPlugin.m_permissions["tom"] = QStringList() << "tom" << "Tom"; /* forge a QDBusMessage */ QDBusMessage msg = QDBusMessage::createMethodCall(peer, "/", "interface", "hi"); SignonDaemonNS::AccessControlManagerHelper helper(&m_acmPlugin); AccessControlManagerHelper::IdentityOwnership ownership = helper.isPeerOwnerOfIdentity(PeerContext(m_conn, msg), 3); QCOMPARE(int(ownership), expectedOwnership); } void AccessControlManagerHelperTest::testIdentityAccess_data() { QTest::addColumn("peer"); QTest::addColumn("ownerList"); QTest::addColumn("acl"); QTest::addColumn("expectedIsAllowed"); QTest::newRow("DB error") << "tom" << (QStringList() << "tom") << (QStringList() << "db-error") << false; QTest::newRow("is owner, ACL empty") << "tom" << (QStringList() << "tom") << QStringList() << true; QTest::newRow("is owner, not in ACL") << "tom" << (QStringList() << "tom") << (QStringList() << "bob") << true; QTest::newRow("is owner, in ACL") << "tom" << (QStringList() << "tom") << (QStringList() << "bob" << "tom" << "harry") << true; QTest::newRow("is owner, ACL=*") << "tom" << (QStringList() << "tom") << (QStringList() << "*") << true; QTest::newRow("not owner, ACL empty") << "tom" << (QStringList() << "bob") << QStringList() << false; QTest::newRow("not owner, not in ACL") << "tom" << (QStringList() << "bob") << (QStringList() << "bob") << false; QTest::newRow("not owner, in ACL") << "tom" << (QStringList() << "bob") << (QStringList() << "bob" << "tom" << "harry") << true; QTest::newRow("not owner, ACL=*") << "tom" << (QStringList() << "bob") << (QStringList() << "*") << true; } void AccessControlManagerHelperTest::testIdentityAccess() { QFETCH(QString, peer); QFETCH(QStringList, ownerList); QFETCH(QStringList, acl); QFETCH(bool, expectedIsAllowed); setDbOwners(ownerList); setDbAcl(acl); m_acmPlugin.m_permissions["tom"] = QStringList() << "tom" << "Tom"; /* forge a QDBusMessage */ QDBusMessage msg = QDBusMessage::createMethodCall(peer, "/", "interface", "hi"); SignonDaemonNS::AccessControlManagerHelper helper(&m_acmPlugin); bool isAllowed = helper.isPeerAllowedToUseIdentity(PeerContext(m_conn, msg), 3); QCOMPARE(isAllowed, expectedIsAllowed); } QTEST_MAIN(AccessControlManagerHelperTest) #include "tst_access_control_manager_helper.moc" signond-nicolasfella/tests/signond-tests/tst_access_control_manager_helper.pro0000664000175000017500000000046614615454535030476 0ustar coucoufcoucoufTARGET = tst_access_control_manager_helper include(signond-tests.pri) SOURCES = \ $${SIGNOND_SRC}/accesscontrolmanagerhelper.cpp \ tst_access_control_manager_helper.cpp HEADERS = \ $${SIGNOND_SRC}/accesscontrolmanagerhelper.h \ $${SIGNOND_SRC}/credentialsdb.h check.commands = "./$$TARGET" signond-nicolasfella/tests/signond-tests/tst_backup.pro0000664000175000017500000000015714615454535023706 0ustar coucoufcoucoufTARGET = tst_backup include(signond-tests.pri) HEADERS += \ backuptest.h SOURCES = \ backuptest.cpp signond-nicolasfella/tests/signond-tests/tst_database.pro0000664000175000017500000000051514615454535024203 0ustar coucoufcoucoufTARGET = tst_database include(signond-tests.pri) HEADERS += \ databasetest.h \ $$TOP_SRC_DIR/src/signond/credentialsdb.h \ $$TOP_SRC_DIR/src/signond/default-secrets-storage.h SOURCES = \ databasetest.cpp \ $$TOP_SRC_DIR/src/signond/credentialsdb.cpp \ $$TOP_SRC_DIR/src/signond/default-secrets-storage.cpp signond-nicolasfella/tests/signond-tests/tst_pluginproxy.pro0000664000175000017500000000041514615454535025036 0ustar coucoufcoucoufTARGET = tst_pluginproxy include(signond-tests.pri) HEADERS += \ testpluginproxy.h \ $$TOP_SRC_DIR/src/signond/pluginproxy.h \ $${TOP_SRC_DIR}/lib/plugins/signon-plugins-common/SignOn/blobiohandler.h SOURCES = \ testpluginproxy.cpp \ include.cpp signond-nicolasfella/tests/signond-tests/tst_signond.cpp0000664000175000017500000005720314615454535024070 0ustar coucoufcoucouf/* * Copyright (C) 2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This file is part of signond * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include "SignOn/UiSessionData" #include "signond/signoncommon.h" #include "fake_signonui.h" namespace QTest { template<> char *toString(const QSet &set) { QByteArray ba = "QSet("; QStringList list = set.toList(); ba += list.join(", "); ba += ")"; return qstrdup(ba.data()); } } // QTest namespace using namespace QtDBusMock; struct SignondSecurityContextTest { public: SignondSecurityContextTest(const QString &systemContext = QStringLiteral("*"), const QString &applicationContext = QStringLiteral("*")): m_systemContext(systemContext), m_applicationContext(applicationContext) { } bool operator==(const SignondSecurityContextTest &sec) const { if (m_systemContext != sec.m_systemContext) return false; return m_applicationContext == sec.m_applicationContext; } bool operator<(const SignondSecurityContextTest &sec) const { if (m_systemContext != sec.m_systemContext) return m_systemContext < sec.m_systemContext; return m_applicationContext < sec.m_applicationContext; } QString m_systemContext; QString m_applicationContext; }; typedef QList SignondSecurityContextTestList; QDebug operator<<(QDebug &dbg, const SignondSecurityContextTestList&securityContextList) { dbg << "{ "; for (const SignondSecurityContextTest &secCtx : securityContextList) { dbg << " ( " << secCtx.m_systemContext << ", " << secCtx.m_applicationContext << " )"; } dbg << " }"; return dbg; } QDBusArgument &operator<<(QDBusArgument &argument, const SignondSecurityContextTest &securityContext) { argument.beginStructure(); argument << securityContext.m_systemContext << securityContext.m_applicationContext; argument.endStructure(); return argument; } const QDBusArgument &operator>>(const QDBusArgument &argument, SignondSecurityContextTest &securityContext) { argument.beginStructure(); argument >> securityContext.m_systemContext >> securityContext.m_applicationContext; argument.endStructure(); return argument; } Q_DECLARE_METATYPE(SignondSecurityContextTest) Q_DECLARE_METATYPE(SignondSecurityContextTestList) class SignondTest: public QObject { Q_OBJECT public: SignondTest(); private Q_SLOTS: void initTestCase(); void cleanup(); void testStart(); void testQueryMethods(); void testQueryMechanisms_data(); void testQueryMechanisms(); void testIdentityCreation(); void testIdentityRemoval(); void testIdentityReferences(); void testAuthSessionMechanisms_data(); void testAuthSessionMechanisms(); void testAuthSessionProcess(); void testAuthSessionProcessFromOtherProcess(); void testAuthSessionProcessUi(); void testAuthSessionCloseUi_data(); void testAuthSessionCloseUi(); private: void setupEnvironment(); bool signondIsRunning(); bool killSignond(); void clearBaseDir(); const QDBusConnection &connection() { return m_dbus.sessionConnection(); } QDBusMessage methodCall(const QString &path, const QString &interface, const QString &method) { return QDBusMessage::createMethodCall(SIGNOND_SERVICE, path, interface, method); } bool replyIsValid(const QDBusMessage &reply); QString createIdentity(const QVariantMap &data, uint *id = 0); private: QTemporaryDir m_baseDir; QtDBusTest::DBusTestRunner m_dbus; QtDBusMock::DBusMock m_mock; FakeSignOnUi m_signonUi; }; static bool mapIsSuperset(const QVariantMap &superSet, const QVariantMap &set) { QMapIterator it(set); while (it.hasNext()) { it.next(); if (!superSet.contains(it.key())) { qDebug() << "Missing key" << it.key(); return false; } if (it.key() == SIGNOND_IDENTITY_INFO_ACL) { QDBusArgument container = superSet.value(it.key()).value(); SignondSecurityContextTestList accessControlList = qdbus_cast(container); SignondSecurityContextTestList sub_acl = it.value().value(); if (accessControlList != sub_acl) { qDebug() << it.key() << "is" << accessControlList << " expecting " << sub_acl; return false; } continue; } if (superSet.value(it.key()) != it.value()) { qDebug() << it.key() << "is" << superSet.value(it.key()) << " expecting " << it.value(); return false; } } return true; } SignondTest::SignondTest(): QObject(0), m_dbus((setupEnvironment(), TEST_DBUS_CONFIG_FILE)), m_mock(m_dbus), m_signonUi(&m_mock) { DBusMock::registerMetaTypes(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); QMetaType::registerComparators(); } void SignondTest::setupEnvironment() { QVERIFY(m_baseDir.isValid()); QByteArray baseDirPath = m_baseDir.path().toUtf8(); QDir baseDir(m_baseDir.path()); qunsetenv("XDG_DATA_DIR"); qputenv("BUILDDIR", BUILDDIR); qputenv("HOME", baseDirPath); qputenv("XDG_RUNTIME_DIR", baseDirPath + "/runtime-dir"); baseDir.mkpath("runtime-dir"); qputenv("SSO_STORAGE_PATH", baseDirPath); qputenv("SSO_EXTENSIONS_DIR", baseDirPath + "/non-existing-dir"); qputenv("SSO_USE_PEER_BUS", "0"); qputenv("SSO_LOGGING_LEVEL", "2"); qputenv("SSO_PLUGINS_DIR", BUILDDIR "/src/plugins/test"); QByteArray ldLibraryPath = qgetenv("LD_LIBRARY_PATH"); qputenv("LD_LIBRARY_PATH", BUILDDIR "/lib/plugins:" BUILDDIR "/lib/plugins/signon-plugins-common:" BUILDDIR "/lib/signond/SignOn:" + ldLibraryPath); QByteArray execPath = qgetenv("PATH"); qputenv("PATH", BUILDDIR "/src/remotepluginprocess:" + execPath); /* Make sure we accidentally don't talk to the developer's signond running * in the session bus */ qunsetenv("DBUS_SESSION_BUS_ADDRESS"); } bool SignondTest::replyIsValid(const QDBusMessage &msg) { if (msg.type() == QDBusMessage::ErrorMessage) { qDebug() << "Error name:" << msg.errorName(); qDebug() << "Error text:" << msg.errorMessage(); } return msg.type() == QDBusMessage::ReplyMessage; } bool SignondTest::signondIsRunning() { return connection(). interface()->isServiceRegistered(SIGNOND_SERVICE).value(); } bool SignondTest::killSignond() { uint pid = connection().interface()->servicePid(SIGNOND_SERVICE).value(); if (pid == 0) return true; return kill(pid, SIGTERM) == 0 || errno == ESRCH; } void SignondTest::clearBaseDir() { QDir baseDir(m_baseDir.path()); baseDir.removeRecursively(); baseDir.mkpath("."); } QString SignondTest::createIdentity(const QVariantMap &data, uint *id) { QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "registerNewIdentity"); msg << QString("application_security_context"); QDBusMessage reply = connection().call(msg); if (!replyIsValid(reply)) return QString(); QString objectPath = reply.arguments()[0].value().path(); msg = methodCall(objectPath, SIGNOND_IDENTITY_INTERFACE, "store"); msg << data; reply = connection().call(msg); if (!replyIsValid(reply)) return QString(); if (id) { *id = reply.arguments()[0].toUInt(); } return objectPath; } void SignondTest::initTestCase() { m_dbus.startServices(); } void SignondTest::cleanup() { if (QTest::currentTestFailed()) { m_baseDir.setAutoRemove(false); qDebug() << "Base dir:" << m_baseDir.path(); } } void SignondTest::testStart() { QVERIFY(killSignond()); QTRY_VERIFY(!signondIsRunning()); QDBusMessage reply = connection().interface()->call("StartServiceByName", SIGNOND_SERVICE, uint(0)); QVERIFY(replyIsValid(reply)); QTRY_VERIFY(signondIsRunning()); } void SignondTest::testQueryMethods() { QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "queryMethods"); QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QCOMPARE(reply.arguments().count(), 1); QStringList methods = reply.arguments()[0].toStringList(); QStringList expectedMethods { "ssotest", "ssotest2" }; QCOMPARE(methods.toSet(), expectedMethods.toSet()); } void SignondTest::testQueryMechanisms_data() { QTest::addColumn("method"); QTest::addColumn("expectedMechanisms"); QTest::newRow("ssotest") << "ssotest" << QStringList { "mech1", "mech2", "mech3", "BLOB" }; QTest::newRow("ssotest2") << "ssotest2" << QStringList { "mech1", "mech2", "mech3" }; } void SignondTest::testQueryMechanisms() { QFETCH(QString, method); QFETCH(QStringList, expectedMechanisms); QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "queryMechanisms"); msg << method; QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QCOMPARE(reply.arguments().count(), 1); QStringList mechanisms = reply.arguments()[0].toStringList(); QCOMPARE(mechanisms.toSet(), expectedMechanisms.toSet()); } void SignondTest::testIdentityCreation() { QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "registerNewIdentity"); msg << QString("application_security_context"); QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QCOMPARE(reply.arguments().count(), 1); QString objectPath = reply.arguments()[0].value().path(); QVERIFY(objectPath.startsWith('/')); SignondSecurityContextTestList acl = { SignondSecurityContextTest() }; QVariantMap identityData { { SIGNOND_IDENTITY_INFO_USERNAME, "John" }, { SIGNOND_IDENTITY_INFO_CAPTION, "John's account" }, { SIGNOND_IDENTITY_INFO_ACL, QVariant::fromValue(acl) }, }; msg = methodCall(objectPath, SIGNOND_IDENTITY_INTERFACE, "store"); msg << identityData; reply = connection().call(msg); QVERIFY(replyIsValid(reply)); uint id = reply.arguments()[0].toUInt(); QVERIFY(id != 0); /* Read the current identity info */ msg = methodCall(objectPath, SIGNOND_IDENTITY_INTERFACE, "getInfo"); reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QVariantMap storedData = QDBusReply(reply).value(); QVERIFY(mapIsSuperset(storedData, identityData)); /* Reload the identity */ msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getIdentity"); msg << id; msg << QString("application_security_context"); reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QCOMPARE(reply.arguments().count(), 2); objectPath = reply.arguments()[0].value().path(); QVERIFY(objectPath.startsWith('/')); storedData = qdbus_cast(reply.arguments()[1].value()); QVERIFY(mapIsSuperset(storedData, identityData)); /* Query identities */ msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "queryIdentities"); msg << QVariantMap(); msg << QString("application_security_context"); reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QCOMPARE(reply.arguments().count(), 1); QList identities = qdbus_cast>(reply.arguments()[0].value()); QCOMPARE(identities.count(), 1); storedData = identities[0]; QVERIFY(mapIsSuperset(storedData, identityData)); } void SignondTest::testIdentityRemoval() { m_signonUi.mockedService().ClearCalls().waitForFinished(); SignondSecurityContextTestList acl = { SignondSecurityContextTest() }; QVariantMap identityData { { SIGNOND_IDENTITY_INFO_USERNAME, "John Deleteme" }, { SIGNOND_IDENTITY_INFO_CAPTION, "John's account" }, { SIGNOND_IDENTITY_INFO_ACL, QVariant::fromValue(acl) }, }; uint id; QString objectPath = createIdentity(identityData, &id); QVERIFY(objectPath.startsWith('/')); QVERIFY(id > 0); QDBusMessage msg = methodCall(objectPath, SIGNOND_IDENTITY_INTERFACE, "remove"); QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); /* Check that signonui has been asked to remove its data */ QList calls = m_signonUi.mockedService().GetMethodCalls("removeIdentityData"); QCOMPARE(calls.count(), 1); MethodCall call = calls.first(); QCOMPARE(call.args().count(), 1); QCOMPARE(call.args().first().toUInt(), id); /* Read the current identity info */ msg = methodCall(objectPath, SIGNOND_IDENTITY_INTERFACE, "getInfo"); reply = connection().call(msg); QCOMPARE(reply.type(), QDBusMessage::ErrorMessage); /* Load the identity again */ msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getIdentity"); msg << id; msg << QString("application_security_context"); reply = connection().call(msg); QCOMPARE(reply.type(), QDBusMessage::ErrorMessage); } void SignondTest::testIdentityReferences() { SignondSecurityContextTestList acl = { SignondSecurityContextTest() }; QVariantMap identityData { { SIGNOND_IDENTITY_INFO_USERNAME, "John" }, { SIGNOND_IDENTITY_INFO_CAPTION, "John's account" }, { SIGNOND_IDENTITY_INFO_ACL, QVariant::fromValue(acl) }, }; QString objectPath = createIdentity(identityData); /* Read the current identity info */ QDBusMessage msg = methodCall(objectPath, SIGNOND_IDENTITY_INTERFACE, "getInfo"); QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QVariantMap storedData = QDBusReply(reply).value(); QCOMPARE(storedData.value(SIGNOND_IDENTITY_INFO_REFCOUNT).toInt(), 0); /* Add a reference */ msg = methodCall(objectPath, SIGNOND_IDENTITY_INTERFACE, "addReference"); msg << "hello"; reply = connection().call(msg); QVERIFY(replyIsValid(reply)); /* Check new refcount */ msg = methodCall(objectPath, SIGNOND_IDENTITY_INTERFACE, "getInfo"); reply = connection().call(msg); QVERIFY(replyIsValid(reply)); storedData = QDBusReply(reply).value(); QEXPECT_FAIL("", "refcount not updated: https://gitlab.com/accounts-sso/signond/issues/1", Continue); QCOMPARE(storedData.value(SIGNOND_IDENTITY_INFO_REFCOUNT).toInt(), 1); } void SignondTest::testAuthSessionMechanisms_data() { QTest::addColumn("method"); QTest::addColumn("wantedMechanisms"); QTest::addColumn("expectedMechanisms"); QTest::newRow("ssotest - any") << "ssotest" << QStringList {} << QStringList { "mech1", "mech2", "mech3", "BLOB" }; QTest::newRow("ssotest - subset") << "ssotest" << QStringList { "BLOB", "mech1" } << QStringList { "BLOB", "mech1" }; QTest::newRow("ssotest2 - any") << "ssotest2" << QStringList {} << QStringList { "mech1", "mech2", "mech3" }; QTest::newRow("ssotest2 - mix") << "ssotest2" << QStringList { "BLOB", "mech1" } << QStringList { "mech1" }; } void SignondTest::testAuthSessionMechanisms() { QFETCH(QString, method); QFETCH(QStringList, wantedMechanisms); QFETCH(QStringList, expectedMechanisms); QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getAuthSessionObjectPath"); msg << uint(0); msg << QString("*"); msg << method; QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QCOMPARE(reply.arguments().count(), 1); QString objectPath = reply.arguments()[0].value().path(); QVERIFY(objectPath.startsWith('/')); /* Check the available mechanisms */ msg = methodCall(objectPath, SIGNOND_AUTH_SESSION_INTERFACE, "queryAvailableMechanisms"); msg << wantedMechanisms; reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QStringList mechanisms = QDBusReply(reply).value(); QCOMPARE(mechanisms.toSet(), expectedMechanisms.toSet()); } void SignondTest::testAuthSessionProcess() { QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getAuthSessionObjectPath"); msg << uint(0); msg << QString("*"); msg << QString("ssotest"); QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QCOMPARE(reply.arguments().count(), 1); QString objectPath = reply.arguments()[0].value().path(); QVERIFY(objectPath.startsWith('/')); QVariantMap sessionData { { "Some key", "its value" }, { "height", 123 }, }; /* Read the current identity info */ msg = methodCall(objectPath, SIGNOND_AUTH_SESSION_INTERFACE, "process"); msg << sessionData; msg << QString("mech1"); reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QVariantMap response = QDBusReply(reply).value(); QVariantMap expectedResponse = sessionData; expectedResponse["Realm"] = "testRealm_after_test"; QCOMPARE(response, expectedResponse); } void SignondTest::testAuthSessionProcessFromOtherProcess() { QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getAuthSessionObjectPath"); msg << uint(0); msg << QString("*"); msg << QString("ssotest"); QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QCOMPARE(reply.arguments().count(), 1); QString objectPath = reply.arguments()[0].value().path(); QVERIFY(objectPath.startsWith('/')); /* Pass this object path to another process, and verify that it's not * allowed to use the session */ QProcess sessionTool; sessionTool.start("./session_tool", { "--sessionPath", objectPath }); QVERIFY(sessionTool.waitForStarted()); QVERIFY(sessionTool.waitForFinished()); QByteArray output = sessionTool.readAllStandardOutput(); QVERIFY(output.startsWith("Error:")); QString errorName = output.mid(6); QCOMPARE(errorName, SIGNOND_PERMISSION_DENIED_ERR_NAME); } void SignondTest::testAuthSessionProcessUi() { QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getAuthSessionObjectPath"); msg << uint(0); msg << QString("*"); msg << QString("ssotest"); QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QString objectPath = reply.arguments()[0].value().path(); QVERIFY(objectPath.startsWith('/')); /* prepare SignOnUi */ m_signonUi.mockedService().ClearCalls().waitForFinished(); QVariantMap uiReply { { "data", QVariantMap { { "UserName", "the user" }, { "Secret", "s3c'r3t" }, { "QueryErrorCode", 0 }, } }, }; m_signonUi.setNextReply(uiReply); /* Start the authentication, using a mechanism requiring UI interaction */ QVariantMap sessionData { { "Some key", "its value" }, { "height", 123 }, }; msg = methodCall(objectPath, SIGNOND_AUTH_SESSION_INTERFACE, "process"); msg << sessionData; msg << QString("mech2"); reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QVariantMap response = QDBusReply(reply).value(); QVariantMap expectedResponse { { "UserName", "the user" }, }; QCOMPARE(response, expectedResponse); } void SignondTest::testAuthSessionCloseUi_data() { QTest::addColumn("uiReply"); QTest::addColumn("expectedCancellation"); QTest::newRow("no UI") << QVariantMap {} << false; QTest::newRow("with UI") << QVariantMap { { "data", QVariantMap { { "UserName", "the user" }, { "Secret", "s3c'r3t" }, { "QueryErrorCode", 0 }, } } } << true; QTest::newRow("with UI error") << QVariantMap { { "error", "some.Dbus.Error" } } << false; QTest::newRow("with UI canceled") << QVariantMap { { "data", QVariantMap { { "UserName", "the user" }, { "Secret", "s3c'r3t" }, { "QueryErrorCode", SignOn::QUERY_ERROR_CANCELED }, } } } << false; } void SignondTest::testAuthSessionCloseUi() { QFETCH(QVariantMap, uiReply); QFETCH(bool, expectedCancellation); QDBusMessage msg = methodCall(SIGNOND_DAEMON_OBJECTPATH, SIGNOND_DAEMON_INTERFACE, "getAuthSessionObjectPath"); msg << uint(0); msg << QString("*"); msg << QString("ssotest"); QDBusMessage reply = connection().call(msg); QVERIFY(replyIsValid(reply)); QString objectPath = reply.arguments()[0].value().path(); QVERIFY(objectPath.startsWith('/')); /* prepare SignOnUi */ OrgFreedesktopDBusMockInterface &mockInterface = m_signonUi.mockedService(); mockInterface.ClearCalls().waitForFinished(); m_signonUi.setNextReply(uiReply); /* Start the authentication; if uiReply is empty, don't invoke signonUI */ QString mechanism = uiReply.isEmpty() ? "mech1" : "mech2"; QVariantMap sessionData { { "Some key", "its value" }, { "height", 123 }, }; msg = methodCall(objectPath, SIGNOND_AUTH_SESSION_INTERFACE, "process"); msg << sessionData; msg << mechanism; connection().call(msg); /* Check whether signonui has been asked to close */ QTRY_COMPARE(mockInterface.GetMethodCalls("cancelUiRequest").value().count(), expectedCancellation ? 1 : 0); } QTEST_GUILESS_MAIN(SignondTest); #include "tst_signond.moc" signond-nicolasfella/tests/signond-tests/tst_signond.pro0000664000175000017500000000103114615454535024072 0ustar coucoufcoucoufinclude(../tests.pri) TARGET = tst_signond CONFIG += \ c++11 \ debug \ link_pkgconfig QT += \ core \ dbus \ testlib PKGCONFIG += \ libqtdbusmock-1 \ libqtdbustest-1 DEFINES += \ BUILDDIR=\\\"$${TOP_BUILD_DIR}\\\" \ SIGNONUI_MOCK_TEMPLATE=\\\"$${PWD}/signonui.py\\\" \ TEST_DBUS_CONFIG_FILE=\\\"../testsession.conf\\\" INCLUDEPATH += \ $${TOP_SRC_DIR}/lib \ $${TOP_SRC_DIR}/lib/plugins SOURCES += \ tst_signond.cpp check.commands = "./$${TARGET}" check.depends = $${TARGET} signond-nicolasfella/tests/signond-tests/tst_timeouts.pro0000664000175000017500000000015514615454535024310 0ustar coucoufcoucoufTARGET = tst_timeouts include(signond-tests.pri) HEADERS += \ timeouts.h SOURCES = \ timeouts.cpp signond-nicolasfella/tests/signond-tests/databasetest.cpp0000664000175000017500000005043114615454547024200 0ustar coucoufcoucouf/* * This file is part of signon * * Copyright (C) 2009-2010 Nokia Corporation. * Copyright (C) 2012-2016 Canonical Ltd. * * Contact: Alberto Mardegan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "databasetest.h" #include "signond/signoncommon.h" #include #include #include "credentialsdb.h" #include "signonidentityinfo.cpp" #include "signonsecuritycontext.cpp" const QString dbFile = QLatin1String("/tmp/signon_test.db"); const QString secretsDbFile = QLatin1String("/tmp/signon_test_secrets.db"); static QSet toSet(const QStringList &list) { #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) return QSet(list.begin(), list.end()); #else return list.toSet(); #endif } void TestDatabase::initTestCase() { QFile::remove(dbFile); QFile::remove(secretsDbFile); m_secretsStorage = new DefaultSecretsStorage(); m_db = new CredentialsDB(dbFile, m_secretsStorage); m_meta = m_db->metaDataDB; QVERIFY(m_db != 0); QStringList mechs = QStringList() << QString::fromLatin1("Mech1") << QString::fromLatin1("Mech2"); testMethods.insert(QLatin1String("Method1"), mechs); testMethods.insert(QLatin1String("Method2"), mechs); testMethods.insert(QLatin1String("Method3"), QStringList()); testRealms = QStringList() << QLatin1String("Realm1.com") << QLatin1String("Realm2.com") << QLatin1String("Realm3.com"); testAcl = QStringList() << QLatin1String("AID::12345678") << QLatin1String("AID::87654321") << QLatin1String("test::property"); } void TestDatabase::cleanupTestCase() { delete m_db; m_db = NULL; delete m_secretsStorage; m_secretsStorage = 0; //remove database file //QFile::remove(dbFile); } void TestDatabase::init() { } void TestDatabase::cleanup() { if (m_db->isSecretsDBOpen()) m_db->closeSecretsDB(); } void TestDatabase::createTableStructureTest() { QVERIFY(!m_meta->hasTables()); m_db->init(); QVERIFY(m_meta->hasTables()); bool success = m_db->openSecretsDB(secretsDbFile); QVERIFY(success); } void TestDatabase::queryListTest() { QString queryStr; /*create test table*/ queryStr = QString::fromLatin1( "CREATE TABLE TESTING" "(identity_id INTEGER ," "realm TEXT," "hostname TEXT," "PRIMARY KEY (identity_id, realm, hostname))"); QSqlQuery insertQuery = m_meta->exec(queryStr); m_meta->commit(); queryStr = QString::fromLatin1( "INSERT INTO TESTING (identity_id, realm) " "VALUES('%1', '%2')") .arg(80).arg(QLatin1String("a")); insertQuery = m_meta->exec(queryStr); queryStr = QString::fromLatin1( "INSERT INTO TESTING (identity_id, realm) " "VALUES('%1', '%2')") .arg(80).arg(QLatin1String("b")); insertQuery = m_meta->exec(queryStr); QStringList list = m_meta->queryList(QString::fromLatin1( "SELECT realm FROM TESTING WHERE identity_id = 80")); QVERIFY(list.contains(QLatin1String("a"))); QVERIFY(list.contains(QLatin1String("b"))); QVERIFY(list.count() == 2); list = m_meta->queryList(QString::fromLatin1( "SELECT realm FROM TESTING WHERE identity_id = 81")); QVERIFY(list.count() == 0); } void TestDatabase::insertMethodsTest() { //test empty list QMap methods; m_meta->insertMethods(methods); QStringList list = m_meta->queryList(QString::fromLatin1( "SELECT method FROM METHODS")); QVERIFY(list.count() == 0); list = m_meta->queryList(QString::fromLatin1( "SELECT mechanism FROM MECHANISMS")); QVERIFY(list.count() == 0); //test real list QStringList mechs = QStringList() << QLatin1String("M1")<< QLatin1String("M2"); methods.insert(QLatin1String("Test"), mechs); methods.insert(QLatin1String("Test2"), mechs); m_meta->insertMethods(methods); list = m_meta->queryList(QString::fromLatin1( "SELECT method FROM METHODS")); qDebug() << list; QVERIFY(list.contains(QLatin1String("Test"))); QVERIFY(list.contains(QLatin1String("Test2"))); QVERIFY(list.count() == 2); list = m_meta->queryList(QString::fromLatin1( "SELECT mechanism FROM MECHANISMS")); qDebug() << list; QVERIFY(list.contains(QLatin1String("M1"))); QVERIFY(list.contains(QLatin1String("M2"))); QVERIFY(list.count() == 2); } void TestDatabase::methodsTest() { quint32 id; SignonIdentityInfo info; info.setMethods(testMethods); id = m_db->insertCredentials(info); QStringList meths = m_db->methods(id); QVERIFY(meths.contains(QLatin1String("Method1"))); QVERIFY(meths.contains(QLatin1String("Method2"))); QVERIFY(meths.contains(QLatin1String("Method3"))); QVERIFY(meths.count() == 3); } void TestDatabase::checkPasswordTest() { quint32 id; m_db->openSecretsDB(secretsDbFile); SignonIdentityInfo info; info.setUserName(QLatin1String("User")); info.setPassword(QLatin1String("Pass")); info.setStorePassword(true); id = m_db->insertCredentials(info); QVERIFY(m_db->checkPassword(id, info.userName(), info.password())); QVERIFY(!m_db->checkPassword(id, info.userName(), QLatin1String("PassWd"))); QVERIFY(!m_db->checkPassword(id, QLatin1String("User2"), info.password())); QVERIFY(!m_db->checkPassword(id, info.userName(), "' or password like '%")); } void TestDatabase::credentialsTest() { m_db->openSecretsDB(secretsDbFile); m_db->clear(); QMap filter; QList creds = m_db->credentials(filter); QVERIFY(creds.count() == 0); SignonIdentityInfo info; info.setCaption(QLatin1String("Caption")); m_db->insertCredentials(info); creds = m_db->credentials(filter); QVERIFY(creds.count() == 1); m_db->insertCredentials(info); creds = m_db->credentials(filter); QVERIFY(creds.count() == 2); foreach(SignonIdentityInfo info, creds) { qDebug() << info.id() << info.caption(); } //TODO check filtering when implemented } void TestDatabase::insertCredentialsTest() { SignonIdentityInfo info; SignonIdentityInfo info2; SignonIdentityInfo retInfo; quint32 id; //insert empty id = m_db->insertCredentials(info); retInfo = m_db->credentials(id, false); QVERIFY(id != info.id()); info.setId(id); QCOMPARE(retInfo.id(), info.id()); //insert with empty acl info = SignonIdentityInfo(); info.setUserName(QLatin1String("User")); info.setPassword(QLatin1String("Pass")); info.setStorePassword(true); info.setMethods(testMethods); info.setRealms(testRealms); id = m_db->insertCredentials(info); retInfo = m_db->credentials(id, false); QVERIFY(id != info.id()); info.setId(id); retInfo.setPassword(info.password()); QCOMPARE(retInfo.id(), info.id()); QCOMPARE(retInfo.password(), info.password()); //insert with empty methods MethodMap methods2; info = SignonIdentityInfo(); info.setUserName(QLatin1String("User")); info.setPassword(QLatin1String("Pass")); info.setStorePassword(true); info.setMethods(methods2); info.setRealms(testRealms); id = m_db->insertCredentials(info2); retInfo = m_db->credentials(id, false); QVERIFY(id != info2.id()); QCOMPARE(retInfo.methods(), info2.methods()); //insert complete info = SignonIdentityInfo(); info.setUserName(QLatin1String("User")); info.setPassword(QLatin1String("Pass")); info.setStorePassword(true); info.setMethods(testMethods); info.setRealms(testRealms); info.setAccessControlList(testAcl); id = m_db->insertCredentials(info); retInfo = m_db->credentials(id, false); QVERIFY(id != info.id()); info.setId(id); QVERIFY(info.password() != retInfo.password()); retInfo.setPassword(info.password()); QCOMPARE(info.methods(), retInfo.methods()); QCOMPARE(retInfo.password(), info.password()); QCOMPARE(retInfo.methods(), info.methods()); //with password and secrets DB disabled id = m_db->insertCredentials(info); retInfo = m_db->credentials(id, true); QVERIFY(id != info.id()); info.setId(id); QCOMPARE(retInfo.id(), info.id()); QCOMPARE(retInfo.password(), info.password()); //with password and secrets DB enabled bool success = m_db->openSecretsDB(secretsDbFile); QVERIFY(success); id = m_db->insertCredentials(info); retInfo = m_db->credentials(id, true); QVERIFY(id != info.id()); info.setId(id); QCOMPARE(retInfo.id(), info.id()); QCOMPARE(retInfo.password(), info.password()); } void TestDatabase::updateCredentialsTest() { SignonIdentityInfo retInfo; quint32 id; bool success = m_db->openSecretsDB(secretsDbFile); QVERIFY(success); //insert complete SignonIdentityInfo info; info.setUserName(QLatin1String("User")); info.setPassword(QLatin1String("Pass")); info.setStorePassword(true); info.setMethods(testMethods); info.setRealms(testRealms); info.setAccessControlList(testAcl); id = m_db->insertCredentials(info); retInfo = m_db->credentials(id, true); info.setId(id); QCOMPARE(retInfo.userName(), info.userName()); //update complete QStringList urealms = QStringList() << QLatin1String("URealm1.com") << QLatin1String("URealm2.com") << QLatin1String("Realm3.com"); MethodMap umethods; QStringList umechs = QStringList() << QString::fromLatin1("UMech1") << QString::fromLatin1("Mech2") ; umethods.insert(QLatin1String("Method1"), umechs); umethods.insert(QLatin1String("UMethod2"), umechs); umethods.insert(QLatin1String("Method3"), QStringList()); SignonIdentityInfo updateInfo; updateInfo.setId(id); updateInfo.setUserName(QLatin1String("UpUser")); updateInfo.setPassword(QLatin1String("UpdatedPass")); updateInfo.setStorePassword(true); updateInfo.setMethods(umethods); updateInfo.setRealms(urealms); updateInfo.setAccessControlList(testAcl); QVERIFY(m_db->updateCredentials(updateInfo)); retInfo = m_db->credentials(id, true); QVERIFY(retInfo.userName() != info.userName()); QCOMPARE(retInfo.userName(), updateInfo.userName()); QCOMPARE(retInfo.password(), updateInfo.password()); QCOMPARE(retInfo.storePassword(), updateInfo.storePassword()); /* The sorting of the method's mechanisms might vary, so we cannot just * compare the whole method map as a whole. */ QCOMPARE(toSet(retInfo.methods().keys()), toSet(updateInfo.methods().keys())); QMapIterator it(retInfo.methods()); while (it.hasNext()) { it.next(); QCOMPARE(toSet(it.value()), toSet(umethods.value(it.key()))); } QCOMPARE(toSet(retInfo.realms()), toSet(updateInfo.realms())); QCOMPARE(toSet(retInfo.accessControlList()), toSet(updateInfo.accessControlList())); } void TestDatabase::removeCredentialsTest() { SignonIdentityInfo retInfo; quint32 id; bool success = m_db->openSecretsDB(secretsDbFile); QVERIFY(success); SignonIdentityInfo info; info.setUserName(QLatin1String("User")); info.setPassword(QLatin1String("Pass")); info.setStorePassword(true); info.setMethods(testMethods); info.setRealms(testRealms); info.setAccessControlList(testAcl); id = m_db->insertCredentials(info); retInfo = m_db->credentials(id, true); QVERIFY(id != info.id()); info.setId(id); QCOMPARE(retInfo.userName(), info.userName()); QSqlQuery query; QString queryStr = QString::fromLatin1( "SELECT * FROM ACL WHERE identity_id = '%1'") .arg(id); query = m_meta->exec(queryStr); QVERIFY(query.first()); QVERIFY(m_db->removeCredentials(id)); retInfo = m_db->credentials(id, true); QVERIFY(retInfo.userName() != info.userName()); QCOMPARE(retInfo.id(), quint32(0)); //check that db is cleared queryStr = QString::fromLatin1( "SELECT * FROM ACL WHERE identity_id = '%1'") .arg(id); query = m_meta->exec(queryStr); QVERIFY(!query.first()); queryStr = QString::fromLatin1( "SELECT * FROM REALMS WHERE identity_id = '%1'") .arg(id); query = m_meta->exec(queryStr); QVERIFY(!query.first()); queryStr = QString::fromLatin1( "SELECT * FROM REFS WHERE identity_id = '%1'") .arg(id); query = m_meta->exec(queryStr); QVERIFY(!query.first()); } void TestDatabase::clearTest() { /* we expact this to fail, because the secrets DB is not available */ QVERIFY(!m_db->clear()); QSqlQuery query = m_meta->exec(QLatin1String("SELECT * FROM credentials")); QVERIFY(query.first()); bool success = m_db->openSecretsDB(secretsDbFile); QVERIFY(success); QVERIFY(m_db->clear()); query = m_meta->exec(QLatin1String("SELECT * FROM credentials")); QVERIFY(!query.first()); } void TestDatabase::dataTest() { quint32 id; QString method = QLatin1String("Method1"); SignonIdentityInfo info; info.setUserName(QLatin1String("User")); info.setPassword(QLatin1String("Pass")); info.setStorePassword(true); info.setMethods(testMethods); info.setRealms(testRealms); info.setAccessControlList(testAcl); id = m_db->insertCredentials(info); /* no secrets DB: data will be cached in memory */ QVariantMap cachedData; cachedData.insert(QLatin1String("James"), QLatin1String("Bond")); bool ret = m_db->storeData(id, method, cachedData); QVERIFY(ret); /* verify that the data is cached */ QCOMPARE(cachedData, m_db->loadData(id, method)); QCOMPARE(m_db->m_secretsCache->m_cache.count(), 1); /* load the secrets DB */ ret = m_db->openSecretsDB(secretsDbFile); QVERIFY(ret); /* the cached data should have been stored into the DB and the * cache should be clear */ QCOMPARE(cachedData, m_db->loadData(id, method)); QVERIFY(m_db->m_secretsCache->m_cache.isEmpty()); /* now store more data, with the secrets DB active */ QVariantMap result; QVariantMap data; data.insert(QLatin1String("token"), QLatin1String("tokenval")); ret = m_db->storeData(id, method, data); QVERIFY(ret); result = m_db->loadData(id, method); qDebug() << result; QCOMPARE(result, data); data.insert(QLatin1String("token"), QLatin1String("tokenvalupdated")); data.insert(QLatin1String("token2"), QLatin1String("tokenval2")); ret = m_db->storeData(id, method, data); QVERIFY(ret); result = m_db->loadData(id, method); QCOMPARE(result, data); data.insert(QLatin1String("token"), QVariant()); data.insert(QLatin1String("token2"), QVariant()); ret = m_db->storeData(id, method, data); QVERIFY(ret); result = m_db->loadData(id, method); qDebug() << data; QVERIFY(result.isEmpty()); ret = m_db->storeData(id, method, QVariantMap()); QVERIFY(ret); result = m_db->loadData(id, method); qDebug() << data; QVERIFY(result.isEmpty()); data.clear(); for ( int i = 1000; i <1000+(SSO_MAX_TOKEN_STORAGE/10) +1 ; i++) { data.insert(QString::fromLatin1("t%1").arg(i), QLatin1String("12345")); } ret = m_db->storeData(id, method, data); QVERIFY(!ret); result = m_db->loadData(id, method); QVERIFY(result != data); data.clear(); QVariantMap map; map.insert("key1",QLatin1String("string")); map.insert("key2",qint32(12)); data.insert("key", map); ret = m_db->storeData(0, method, data); QVERIFY(!ret); result = m_db->loadData(0, method); QVERIFY(result.isEmpty()); data.insert(QLatin1String("token"), QLatin1String("tokenvalupdated")); data.insert(QLatin1String("token2"), QLatin1String("tokenval2")); ret = m_db->storeData(id, method, data); QVERIFY(ret); ret = m_db->removeData(id, method); QVERIFY(ret); result = m_db->loadData(id, method); QVERIFY(result.isEmpty()); } void TestDatabase::referenceTest() { quint32 id; SignonIdentityInfo info; info.setUserName(QLatin1String("User")); id = m_db->insertCredentials(info); //add reference bool ret = m_db->addReference(id, QLatin1String("AID::12345678"), QLatin1String("ref1")); QVERIFY(ret); QStringList refs = m_db->references(id); qDebug() << refs; QVERIFY(refs.contains(QLatin1String("ref1"))); refs = m_db->references(id,QLatin1String("AID::12345678")); QVERIFY(refs.contains(QLatin1String("ref1"))); refs = m_db->references(id,QLatin1String("AID::1234567")); QVERIFY(!refs.contains(QLatin1String("ref1"))); //remove references ret = m_db->removeReference(id, QLatin1String("AID::12345678")); QVERIFY(ret); refs = m_db->references(id); qDebug() << refs; QVERIFY(!refs.contains(QLatin1String("ref1"))); //add new and remove nonexisting reference ret = m_db->addReference(id, QLatin1String("AID::12345678"), QLatin1String("ref1")); QVERIFY(ret); ret = m_db->removeReference(id, QLatin1String("AID::12345678"), QLatin1String("ref2")); QVERIFY(!ret); refs = m_db->references(id); qDebug() << refs; QVERIFY(refs.contains(QLatin1String("ref1"))); //remove specific reference ret = m_db->removeReference(id, QLatin1String("AID::12345678"), QLatin1String("ref1")); QVERIFY(ret); refs = m_db->references(id); qDebug() << refs; QVERIFY(!refs.contains(QLatin1String("ref1"))); } void TestDatabase::cacheTest() { quint32 idWithStore, idWithoutStore; SignonIdentityInfo info; info.setUserName(QLatin1String("User")); info.setPassword(QLatin1String("Pass")); info.setStorePassword(true); /* no secrets DB: data will be cached in memory */ idWithStore = m_db->insertCredentials(info); QVERIFY(idWithStore != 0); info.setPassword("Pass2"); info.setStorePassword(false); idWithoutStore = m_db->insertCredentials(info); QVERIFY(idWithoutStore != 0); /* verify that the password is cached */ info = m_db->credentials(idWithStore, true); QCOMPARE(info.password(), QLatin1String("Pass")); info = m_db->credentials(idWithoutStore, true); QCOMPARE(info.password(), QLatin1String("Pass2")); /* load the secrets DB */ int ret = m_db->openSecretsDB(secretsDbFile); QVERIFY(ret); /* the cached data should have been stored into the DB, but not for * idWithoutStore, which has storeSecret set to false. */ QString username, password; bool ok; ok = m_db->secretsStorage->loadCredentials(idWithStore, username, password); QVERIFY(ok); QCOMPARE(password, QLatin1String("Pass")); ok = m_db->secretsStorage->loadCredentials(idWithoutStore, username, password); QVERIFY(!ok); } void TestDatabase::accessControlListTest() { quint32 id; SignonIdentityInfo info; info.setUserName(QLatin1String("User")); info.setAccessControlList(testAcl); id = m_db->insertCredentials(info); QStringList acl = m_db->accessControlList(id); qDebug() << acl; QCOMPARE(acl, info.accessControlList()); } void TestDatabase::credentialsOwnerSecurityTokenTest() { quint32 id; SignonIdentityInfo info; info.setUserName(QLatin1String("User")); info.setOwnerList(testAcl); id = m_db->insertCredentials(info); QString token = m_db->credentialsOwnerSecurityToken(id); QCOMPARE(token, QLatin1String("AID::12345678")); QStringList tokens = m_db->ownerList(id); QCOMPARE(toSet(tokens), toSet(testAcl)); } QTEST_MAIN(TestDatabase) signond-nicolasfella/tests/signond-tests/identity-tool.pro0000664000175000017500000000053514615454547024356 0ustar coucoufcoucoufinclude(../../common-project-config.pri) TEMPLATE = app TARGET = identity-tool QT += core QT -= gui LIBS += -lsignon-qt$${QT_MAJOR_VERSION} QMAKE_LIBDIR += \ $${TOP_BUILD_DIR}/lib/signond/SignOn \ $${TOP_BUILD_DIR}/lib/SignOn QMAKE_RPATHDIR = $${QMAKE_LIBDIR} INCLUDEPATH += \ $${TOP_SRC_DIR}/lib SOURCES = \ identity-tool.cpp signond-nicolasfella/tests/signond-tests/signond-tests.pri0000664000175000017500000000151614615454547024345 0ustar coucoufcoucoufinclude(../tests.pri) QT += core \ sql \ testlib \ xml \ network \ dbus QT -= gui LIBS += \ -lsignon-extension \ -lsignon-qt$${QT_MAJOR_VERSION} QMAKE_LIBDIR += \ $${TOP_BUILD_DIR}/lib/signond/SignOn \ $${TOP_BUILD_DIR}/lib/SignOn QMAKE_RPATHDIR = $${QMAKE_LIBDIR} SIGNOND_SRC = $${TOP_SRC_DIR}/src/signond DEFINES += SIGNOND_TRACE DEFINES += SIGNON_PLUGIN_TRACE INCLUDEPATH += . \ $$TOP_SRC_DIR/lib/plugins \ $$TOP_SRC_DIR/lib/signond \ $$TOP_SRC_DIR/src/signond \ $${TOP_SRC_DIR}/lib/plugins/signon-plugins-common \ $${TOP_SRC_DIR}/lib/plugins/signon-plugins-common/SignOn \ $${TOP_SRC_DIR}/lib \ check.depends = $$TARGET check.commands = "SSO_PLUGINS_DIR=$${TOP_BUILD_DIR}/src/plugins/test SSO_EXTENSIONS_DIR=$${TOP_BUILD_DIR}/non-existing-dir $$RUN_WITH_SIGNOND ./$$TARGET" signond-nicolasfella/tests/signond.sh0000775000175000017500000000022414615454535020217 0ustar coucoufcoucouf#! /bin/sh set -e BUILDDIR="${BUILDDIR:=..}" SIGNOND="${BUILDDIR}/src/signond/signond" echo "Starting signond from $SIGNOND" $WRAPPER $SIGNOND signond-nicolasfella/tests/tests.pri0000664000175000017500000000046314615454535020102 0ustar coucoufcoucoufinclude( ../common-project-config.pri ) include( $$TOP_SRC_DIR/common-vars.pri ) RUN_WITH_SIGNOND = "BUILDDIR=$$TOP_BUILD_DIR SRCDIR=$$TOP_SRC_DIR $$TOP_SRC_DIR/tests/run-with-signond.sh" QMAKE_EXTRA_TARGETS += check CONFIG(install_tests) { target.path = $${INSTALL_TESTDIR} INSTALLS += target } signond-nicolasfella/tests/tests.pro0000664000175000017500000000071014615454535020103 0ustar coucoufcoucoufinclude( ../common-project-config.pri ) include( ../common-vars.pri ) TEMPLATE = subdirs CONFIG += ordered SUBDIRS += \ passwordplugintest \ libsignon-qt-tests \ signond-tests \ extensions QMAKE_SUBSTITUTES += com.google.code.AccountsSSO.SingleSignOn.service.in # copy testsession.conf to the build directory system($$QMAKE_COPY testsession.conf.in $${TOP_BUILD_DIR}/tests/testsession.conf) QMAKE_DISTCLEAN += \ testsession.conf signond-nicolasfella/tests/testsession.conf.in0000664000175000017500000000314714615454535022065 0ustar coucoufcoucouf session unix:tmpdir=/tmp . 60000 1000000000 1000000000 1000000000 120000 240000 100000 10000 100000 10000 50000 50000 50000 300000 signond-nicolasfella/.gitlab-ci.yml0000664000175000017500000000475214615454547017526 0ustar coucoufcoucoufcache: key: apt-cache paths: - apt-cache/ build_amd64: stage: build image: ubuntu:bionic before_script: - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR - apt-get update -yq && apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y qt5-qmake qt5-default qtbase5-dev qtchooser pkg-config libqt5sql5-sqlite doxygen libdbus-1-dev script: - mkdir build - cd build - qmake CONFIG+=debug CONFIG+=coverage CONFIG+=enable-backup CONFIG+=enable-p2p .. - make -j 4 artifacts: paths: - build/ test_amd64: stage: test image: ubuntu:bionic before_script: - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR - apt-get update -yq && apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y dbus-test-runner libqtdbusmock1-dev libqtdbustest1-dev lcov gcovr make qt5-qmake qt5-default qtbase5-dev qtchooser pkg-config libqt5sql5-sqlite doxygen libdbus-1-dev script: - find build | xargs touch # Avoid rebuilding - cd build - make coverage-html dependencies: - build_amd64 artifacts: paths: - ./ build_amd64_qt6: stage: build image: ubuntu:jammy before_script: - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR - apt-get update -yq && apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y qmake6 qt6-base-dev pkg-config libqt6sql6-sqlite doxygen libdbus-1-dev g++ make script: - mkdir build - cd build - qmake6 CONFIG+=debug CONFIG+=coverage CONFIG+=enable-backup CONFIG+=enable-p2p .. - make -j 4 artifacts: paths: - build/ test_amd64_qt6: stage: test image: ubuntu:jammy before_script: - export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR - export DEBIAN_FRONTEND=noninteractive - apt-get update -yq && apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y dbus-test-runner libqtdbusmock1-dev libqtdbustest1-dev lcov gcovr make qmake6 qt6-base-dev pkg-config libqt6sql6-sqlite doxygen libdbus-1-dev g++ make script: - find build | xargs touch # Avoid rebuilding - cd build - make coverage-html dependencies: - build_amd64_qt6 artifacts: paths: - ./ pages: stage: deploy script: - cd build - make install INSTALL_ROOT=$(pwd)/out - cd .. - mkdir public - cp -a build/coverage-html public/coverage - cp -a build/out/usr/share/doc/libsignon-qt/html/* public dependencies: - test_amd64 artifacts: paths: - public only: - master signond-nicolasfella/common-project-config.pri0000664000175000017500000000664114615454547022004 0ustar coucoufcoucouf#----------------------------------------------------------------------------- # Common configuration for all projects. #----------------------------------------------------------------------------- QT -= gui CONFIG += link_pkgconfig #MOC_DIR = .moc #OBJECTS_DIR = .obj RCC_DIR = resources #UI_DIR = ui #UI_HEADERS_DIR = ui/include #UI_SOURCES_DIR = ui/src # we don't like warnings... QMAKE_CXXFLAGS -= -Werror -Wno-write-strings # Disable exceptions CONFIG += exceptions_off # Use C++11 CONFIG += c++11 isEmpty(TOP_SRC_DIR) { TOP_SRC_DIR = $$PWD TOP_BUILD_DIR = $${TOP_SRC_DIR}/$${BUILD_DIR} } #DEFINES += QT_NO_DEBUG_OUTPUT DEFINES += DEBUG_ENABLED #TODO comment this to restrict plugins to run under signon user DEFINES += NO_SIGNON_USER # Library name for CMake and pkg-config LIBSIGNON = libsignon-qt$${QT_MAJOR_VERSION} CMAKE_BASENAME = SignOnQt$${QT_MAJOR_VERSION} #----------------------------------------------------------------------------- # setup the installation prefix #----------------------------------------------------------------------------- INSTALL_PREFIX = /usr # default installation prefix # default prefix can be overriden by defining PREFIX when running qmake isEmpty( PREFIX ) { message("====") message("==== NOTE: To override the installation path run: `qmake PREFIX=/custom/path'") message("==== (current installation path is `$${INSTALL_PREFIX}')") } else { INSTALL_PREFIX = $${PREFIX} message("====") message("==== install prefix set to `$${INSTALL_PREFIX}'") } # Setup the library installation directory exists( meego-release ) { ARCH = $$system(tail -n1 meego-release) } else { ARCH = $$system(uname -m) } linux-g++-64|linux-icc-64: INSTALL_LIBDIR = $${INSTALL_PREFIX}/lib64 else: linux-g++-32|linux-icc-32: INSTALL_LIBDIR = $${INSTALL_PREFIX}/lib32 else: INSTALL_LIBDIR = $${INSTALL_PREFIX}/lib # default library directory can be overriden by defining LIBDIR when # running qmake isEmpty( LIBDIR ) { message("====") message("==== NOTE: To override the library installation path run: `qmake LIBDIR=/custom/path'") message("==== (current installation path is `$${INSTALL_LIBDIR}')") } else { INSTALL_LIBDIR = $${LIBDIR} message("====") message("==== library install path set to `$${INSTALL_LIBDIR}'") } isEmpty ( CMAKE_CONFIG_PATH ) { CMAKE_CONFIG_PATH = $${INSTALL_LIBDIR}/cmake/$${CMAKE_BASENAME} message("====") message("==== NOTE: To override the cmake module installation path run: `qmake CMAKE_CONFIG_PATH=/custom/path'") message("==== (current installation path is `$${CMAKE_CONFIG_PATH}')") } else { message("====") message("==== cmake module install path set to `$${CMAKE_CONFIG_PATH}'") } # Default directory for signond extensions _EXTENSIONS = $$(SIGNOND_EXTENSIONS_DIR) isEmpty(_EXTENSIONS) { SIGNOND_EXTENSIONS_DIR = $${INSTALL_LIBDIR}/signon/extensions } else { SIGNOND_EXTENSIONS_DIR = $$_EXTENSIONS } SIGNOND_EXTENSIONS_DIR_QUOTED = \\\"$$SIGNOND_EXTENSIONS_DIR\\\" _PLUGINS = $$(SIGNOND_PLUGINS_DIR) isEmpty(_PLUGINS) { SIGNOND_PLUGINS_DIR = $${INSTALL_LIBDIR}/signon } else { SIGNOND_PLUGINS_DIR = $$_PLUGINS } SIGNOND_PLUGINS_DIR_QUOTED = \\\"$$SIGNOND_PLUGINS_DIR\\\" # Note that you have to CONFIG+=install_tests in order to install tests isEmpty(TESTDIR) { INSTALL_TESTDIR = $${INSTALL_LIBDIR}/signon } else { INSTALL_TESTDIR = $${TESTDIR} } include( coverage.pri )