From dbc765a8f2741cfb6d90557c8e96414a61174926 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 18 Dec 2011 01:35:15 -0600 Subject: [PATCH] Initial import --- COPYING | 504 +++++++++++++++++ README | 16 + configure | 590 ++++++++++++++++++++ openssl.qcm | 80 +++ prepare | 5 + qca-tls.cpp | 1483 +++++++++++++++++++++++++++++++++++++++++++++++++ qca-tls.h | 32 ++ qca-tls.pro | 26 + qca-tls.qc | 9 + qca.h | 468 ++++++++++++++++ qcaprovider.h | 191 +++++++ qcextra | 9 + 12 files changed, 3413 insertions(+) create mode 100644 COPYING create mode 100644 README create mode 100755 configure create mode 100644 openssl.qcm create mode 100755 prepare create mode 100644 qca-tls.cpp create mode 100644 qca-tls.h create mode 100644 qca-tls.pro create mode 100644 qca-tls.qc create mode 100644 qca.h create mode 100644 qcaprovider.h create mode 100755 qcextra diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b1e3f5a --- /dev/null +++ b/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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! + + diff --git a/README b/README new file mode 100644 index 0000000..eb3d5b3 --- /dev/null +++ b/README @@ -0,0 +1,16 @@ +TQCA TLS Plugin v1.0 +------------------- +Author: Justin Karneges +Date: September 15th, 2003 + +This is a plugin to provide SSL/TLS capability to programs that +utilize the TQt Cryptographic Architecture (TQCA). + +Requirements: + OpenSSL Library (http://www.openssl.org/) + +Installation procedure: + ./configure + make + su -c "make install" + diff --git a/configure b/configure new file mode 100755 index 0000000..27a3958 --- /dev/null +++ b/configure @@ -0,0 +1,590 @@ +#!/bin/sh + +show_usage() { +cat <$1/modules.cpp <getenv("QC_WITH_OPENSSL_INC"); + if(!s.isEmpty()) { + if(!conf->checkHeader(s, "openssl/ssl.h")) + return false; + inc = s; + } + else { + if(!conf->findHeader("openssl/ssl.h", TQStringList(), &s)) + return false; + inc = s; + } + + s = conf->getenv("QC_WITH_OPENSSL_LIB"); + if(!s.isEmpty()) { + if(!conf->checkLibrary(s, "ssl")) + return false; + lib = s; + } + else { + if(!conf->findLibrary("ssl", &s)) + return false; + lib = s; + } + + // is it at least openssl 0.9.7? + TQString str = + "#include\n" + "int main()\n" + "{\n" + " unsigned long x = OPENSSL_VERSION_NUMBER;\n" + " if(x >= 0x00907000) return 0; else return 1;\n" + "}\n"; + TQString ext; + if(!inc.isEmpty()) + ext += TQString("-I") + inc + ' '; + if(kb) + ext += TQString("-I") + kbdir + ' '; + if(!lib.isEmpty()) + ext += TQString("-L") + lib + " -lssl -lcrypto "; + int ret; + if(!conf->doCompileAndLink(str, ext, &ret)) + return false; + if(ret == 0) + conf->addDefine("OSSL_097"); + + if(!inc.isEmpty()) + conf->addIncludePath(inc); + if(kb) + conf->addIncludePath(kbdir); + if(!lib.isEmpty()) + conf->addLib(TQString("-L") + s); + conf->addLib("-lssl -lcrypto"); + + // Make sure tqtinterface can be found + conf->addIncludePath("/usr/include/tqt"); + + return true; + } +}; + +EOT +cat >$1/modules_new.cpp <required = true; + o->disabled = false; + +EOT +cat >$1/conf.cpp < +#include +#include +#include +#include +#include +#include +#include +#include + +class Conf; + +class ConfObj +{ +public: + ConfObj(Conf *c); + virtual ~ConfObj(); + + virtual TQString name() const=0; + virtual TQString shortname() const=0; + virtual bool exec()=0; + + Conf *conf; + bool required; + bool disabled; +}; + +typedef TQPtrList ConfObjList; +typedef TQPtrListIterator ConfObjListIt; + +class Conf +{ +public: + Conf() : vars(17) + { + list.setAutoDelete(true); + vars.setAutoDelete(true); + + vars.insert("QMAKE_INCDIR_X11", new TQString(X11_INC)); + vars.insert("QMAKE_LIBDIR_X11", new TQString(X11_LIBDIR)); + vars.insert("QMAKE_LIBS_X11", new TQString(X11_LIB)); + vars.insert("QMAKE_CC", new TQString(CC)); + } + + ~Conf() + { + } + + void added(ConfObj *o) + { + list.append(o); + } + + TQString getenv(const TQString &var) + { + char *p = ::getenv(var.latin1()); + if(!p) + return TQString::null; + return TQString(p); + } + + bool exec() + { + ConfObjListIt it(list); + for(ConfObj *o; (o = it.current()); ++it) { + // if this was a disabled-by-default option, check if it was enabled + if(o->disabled) { + TQString v = TQString("QC_ENABLE_") + o->shortname(); + if(getenv(v) != "Y") + continue; + } + // and the opposite? + else { + TQString v = TQString("QC_DISABLE_") + o->shortname(); + if(getenv(v) == "Y") + continue; + } + + printf("Checking for %s ...", o->name().latin1()); + fflush(stdout); + bool ok = o->exec(); + if(ok) + printf(" yes\n"); + else + printf(" no\n"); + if(!ok && o->required) { + printf("\nError: need %s!\n", o->name().latin1()); + return false; + } + } + return true; + } + + const TQString & qvar(const TQString &s) + { + TQString *p = vars.find(s); + if(p) + return *p; + else + return blank; + } + + TQString expandIncludes(const TQString &inc) + { + return TQString("-I") + inc; + } + + TQString expandLibs(const TQString &lib) + { + return TQString("-L") + lib; + } + + int doCommand(const TQString &s) + { + //printf("[%s]\n", s.latin1()); + int r = system((s + " 1>/dev/null 2>/dev/null").latin1()); + //printf("returned: %d\n", r); + return r; + } + + bool doCompileAndLink(const TQString &filedata, const TQString &flags, int *retcode=0) + { + TQDir dir("."); + TQString fname = "atest.c"; + TQString out = "atest"; + TQFile f(fname); + TQCString cs = filedata.latin1(); + if(!f.open(IO_WriteOnly | IO_Truncate)) + return false; + f.writeBlock(cs.data(), cs.length()); + f.close(); + + TQString str = qvar("QMAKE_CC") + ' ' + fname + " -o " + out + ' ' + flags; + int r = doCommand(str); + if(r == 0 && retcode) + *retcode = doCommand(TQString("./") + out); + dir.remove(fname); + dir.remove(out); + if(r != 0) + return false; + return true; + } + + bool checkHeader(const TQString &path, const TQString &h) + { + TQFileInfo fi(path + '/' + h); + if(fi.exists()) + return true; + return false; + } + + bool findHeader(const TQString &h, const TQStringList &ext, TQString *inc) + { + if(checkHeader("/usr/include", h)) { + *inc = ""; + return true; + } + TQStringList dirs; + dirs += "/usr/local/include"; + dirs += ext; + for(TQStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) { + if(checkHeader(*it, h)) { + *inc = *it; + return true; + } + } + return false; + } + + bool checkLibrary(const TQString &path, const TQString &name) + { + TQString str = + "int main()\n" + "{\n" + " return 0;\n" + "}\n"; + + TQString extra; + if(!path.isEmpty()) + extra += TQString("-L") + path + ' '; + extra += TQString("-l") + name; + if(!doCompileAndLink(str, extra)) + return false; + return true; + } + + bool findLibrary(const TQString &name, TQString *lib) + { + if(checkLibrary("", name)) { + *lib = ""; + return true; + } + if(checkLibrary("/usr/local/lib", name)) { + *lib = "/usr/local/lib"; + return true; + } + return false; + } + + void addDefine(const TQString &str) + { + if(DEFINES.isEmpty()) + DEFINES = str; + else + DEFINES += TQString(" ") + str; + } + + void addLib(const TQString &str) + { + if(LIBS.isEmpty()) + LIBS = str; + else + LIBS += TQString(" ") + str; + } + + void addIncludePath(const TQString &str) + { + if(INCLUDEPATH.isEmpty()) + INCLUDEPATH = str; + else + INCLUDEPATH += TQString(" ") + str; + } + + void addExtra(const TQString &str) + { + extra += str + '\n'; + } + + TQString DEFINES; + TQString INCLUDEPATH; + TQString LIBS; + TQString extra; + +private: + ConfObjList list; + TQDict vars; + TQString blank; +}; + +ConfObj::ConfObj(Conf *c) +{ + conf = c; + conf->added(this); + required = false; + disabled = false; +} + +ConfObj::~ConfObj() +{ +} + +#include"modules.cpp" + +//---------------------------------------------------------------------------- +// main +//---------------------------------------------------------------------------- +int main() +{ + Conf *conf = new Conf; + ConfObj *o; + o = 0; +#include"modules_new.cpp" + + printf("ok\n"); + bool success = false; + if(conf->exec()) { + TQFile f("conf.pri"); + if(!f.open(IO_WriteOnly | IO_Truncate)) { + printf("Error writing %s\n", f.name().latin1()); + return 1; + } + + TQString str; + str += "# qconf\n"; + str += "QT_PATH_PLUGINS = " + TQString(qInstallPathPlugins()) + '\n'; + if(!conf->DEFINES.isEmpty()) + str += "DEFINES += " + conf->DEFINES + '\n'; + if(!conf->INCLUDEPATH.isEmpty()) + str += "INCLUDEPATH += " + conf->INCLUDEPATH + '\n'; + if(!conf->LIBS.isEmpty()) + str += "LIBS += " + conf->LIBS + '\n'; + if(!conf->extra.isEmpty()) + str += conf->extra; + str += '\n'; + + char *p = getenv("BINDIR"); + if(p) { + str += TQString("target.path = ") + p + '\n'; + str += "INSTALLS += target\n"; + } + + TQCString cs = str.latin1(); + f.writeBlock(cs.data(), cs.length()); + f.close(); + success = true; + } + delete conf; + + if(success) + return 0; + else + return 1; +} + +EOT +cat >$1/conf.pro </dev/null + QTDIR=$QTDIR make clean >/dev/null 2>&1 + QTDIR=$QTDIR make >../conf.log 2>&1 +) + +if [ "$?" != "0" ]; then + rm -rf .qconftemp + echo fail + echo + echo "There was an error compiling 'conf'. Be sure you have a proper" + echo "TQt 3.x Multithreaded (MT) build environment set up." + if [ ! -f "$QTDIR/lib/libtqt-mt.so.3" ]; then + echo + echo "One possible reason is that you don't have" + echo "libtqt-mt.so.3 installed in $QTDIR/lib/." + fi + echo + exit 1; +fi + +.qconftemp/conf +ret="$?" +if [ "$ret" = "1" ]; then + rm -rf .qconftemp + echo + exit 1; +else + if [ "$ret" != "0" ]; then + rm -rf .qconftemp + echo fail + echo + echo Unexpected error launching 'conf' + echo + exit 1; + fi +fi +rm -rf .qconftemp + +if [ -x "./qcextra" ]; then + ./qcextra +fi +# run qmake +if expr match "$DEB_BUILD_OPTIONS" ".*nostrip"; then + $qm QMAKE_STRIP=true qca-tls.pro +else + $qm qca-tls.pro +fi +if [ "$?" != "0" ]; then + echo + exit 1; +fi +cat >Makefile.tmp <> Makefile.tmp +rm -f Makefile +cp -f Makefile.tmp Makefile +rm -f Makefile.tmp + +echo +echo Good, your configure finished. Now run \'make\'. +echo diff --git a/openssl.qcm b/openssl.qcm new file mode 100644 index 0000000..242ad20 --- /dev/null +++ b/openssl.qcm @@ -0,0 +1,80 @@ +/* +-----BEGIN QCMOD----- +name: OpenSSL +arg: with-openssl-inc=[path],Path to OpenSSL include files +arg: with-openssl-lib=[path],Path to OpenSSL library files +-----END QCMOD----- +*/ +class qc_openssl : public ConfObj +{ +public: + qc_openssl(Conf *c) : ConfObj(c) {} + QString name() const { return "OpenSSL"; } + QString shortname() const { return "openssl"; } + bool exec() + { + QString inc, lib; + QString s; + bool kb = false; + QString kbdir = "/usr/kerberos/include"; + + // Redhat 9? + if(QFileInfo(kbdir).exists()) + kb = true; + + s = conf->getenv("QC_WITH_OPENSSL_INC"); + if(!s.isEmpty()) { + if(!conf->checkHeader(s, "openssl/ssl.h")) + return false; + inc = s; + } + else { + if(!conf->findHeader("openssl/ssl.h", QStringList(), &s)) + return false; + inc = s; + } + + s = conf->getenv("QC_WITH_OPENSSL_LIB"); + if(!s.isEmpty()) { + if(!conf->checkLibrary(s, "ssl")) + return false; + lib = s; + } + else { + if(!conf->findLibrary("ssl", &s)) + return false; + lib = s; + } + + // is it at least openssl 0.9.7? + QString str = + "#include\n" + "int main()\n" + "{\n" + " unsigned long x = OPENSSL_VERSION_NUMBER;\n" + " if(x >= 0x00907000) return 0; else return 1;\n" + "}\n"; + QString ext; + if(!inc.isEmpty()) + ext += QString("-I") + inc + ' '; + if(kb) + ext += QString("-I") + kbdir + ' '; + if(!lib.isEmpty()) + ext += QString("-L") + lib + " -lssl -lcrypto "; + int ret; + if(!conf->doCompileAndLink(str, ext, &ret)) + return false; + if(ret == 0) + conf->addDefine("OSSL_097"); + + if(!inc.isEmpty()) + conf->addIncludePath(inc); + if(kb) + conf->addIncludePath(kbdir); + if(!lib.isEmpty()) + conf->addLib(QString("-L") + s); + conf->addLib("-lssl -lcrypto"); + + return true; + } +}; diff --git a/prepare b/prepare new file mode 100755 index 0000000..d7936f4 --- /dev/null +++ b/prepare @@ -0,0 +1,5 @@ +#!/bin/sh + +cp ../../src/qca.h . +cp ../../src/qcaprovider.h . + diff --git a/qca-tls.cpp b/qca-tls.cpp new file mode 100644 index 0000000..25f9e77 --- /dev/null +++ b/qca-tls.cpp @@ -0,0 +1,1483 @@ +/* + * qca-tls.cpp - TLS plugin for TQCA + * Copyright (C) 2003 Justin Karneges + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include"qca-tls.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef OSSL_097 +#define NO_AES +#endif + +static TQByteArray lib_randomArray(int size) +{ + if(RAND_status() == 0) { + srand(time(NULL)); + char buf[128]; + for(int n = 0; n < 128; ++n) + buf[n] = rand(); + RAND_seed(buf, 128); + } + TQByteArray a(size); + RAND_bytes((unsigned char *)a.data(), a.size()); + return a; +} + +static bool lib_generateKeyIV(const EVP_CIPHER *_type, const TQByteArray &data, const TQByteArray &salt, TQByteArray *key, TQByteArray *iv, int keysize=-1) +{ + TQByteArray k, i; + unsigned char *kp = 0; + unsigned char *ip = 0; + EVP_CIPHER type = *_type; + if(keysize != -1) + type.key_len = keysize; + if(key) { + k.resize(type.key_len); + kp = (unsigned char *)k.data(); + } + if(iv) { + i.resize(type.iv_len); + ip = (unsigned char *)i.data(); + } + if(!EVP_BytesToKey(&type, EVP_sha1(), (unsigned char *)salt.data(), (unsigned char *)data.data(), data.size(), 1, kp, ip)) + return false; + if(key) + *key = k; + if(iv) + *iv = i; + return true; +} + +static void appendArray(TQByteArray *a, const TQByteArray &b) +{ + int oldsize = a->size(); + a->resize(oldsize + b.size()); + memcpy(a->data() + oldsize, b.data(), b.size()); +} + +static TQByteArray bio2buf(BIO *b) +{ + TQByteArray buf; + while(1) { + char block[1024]; + int ret = BIO_read(b, block, 1024); + int oldsize = buf.size(); + buf.resize(oldsize + ret); + memcpy(buf.data() + oldsize, block, ret); + if(ret != 1024) + break; + } + BIO_free(b); + return buf; +} + +class SHA1Context : public TQCA_HashContext +{ +public: + SHA1Context() + { + reset(); + } + + TQCA_HashContext *clone() + { + return new SHA1Context(*this); + } + + void reset() + { + SHA1_Init(&c); + } + + void update(const char *in, unsigned int len) + { + SHA1_Update(&c, in, len); + } + + void final(TQByteArray *out) + { + TQByteArray buf(20); + SHA1_Final((unsigned char *)buf.data(), &c); + *out = buf; + } + + SHA_CTX c; +}; + +class MD5Context : public TQCA_HashContext +{ +public: + MD5Context() + { + reset(); + } + + TQCA_HashContext *clone() + { + return new MD5Context(*this); + } + + void reset() + { + MD5_Init(&c); + } + + void update(const char *in, unsigned int len) + { + MD5_Update(&c, in, len); + } + + void final(TQByteArray *out) + { + TQByteArray buf(16); + MD5_Final((unsigned char *)buf.data(), &c); + *out = buf; + } + + MD5_CTX c; +}; + +class EVPCipherContext : public TQCA_CipherContext +{ +public: + EVPCipherContext() + { + type = 0; + } + + virtual ~EVPCipherContext() + { + if(type) { + EVP_CIPHER_CTX_cleanup(&c); + type = 0; + } + } + + TQCA_CipherContext *clone() + { + EVPCipherContext *cc = cloneSelf(); + cc->r = r.copy(); + return cc; + } + + virtual EVPCipherContext *cloneSelf() const=0; + virtual const EVP_CIPHER *getType(int mode) const=0; + + int keySize() { return getType(TQCA::CBC)->key_len; } + int blockSize() { return getType(TQCA::CBC)->block_size; } + + bool generateKey(char *out, int keysize) + { + TQByteArray a; + if(!lib_generateKeyIV(getType(TQCA::CBC), lib_randomArray(128), lib_randomArray(2), &a, 0, keysize)) + return false; + memcpy(out, a.data(), a.size()); + return true; + } + + bool generateIV(char *out) + { + TQByteArray a; + if(!lib_generateKeyIV(getType(TQCA::CBC), lib_randomArray(128), lib_randomArray(2), 0, &a)) + return false; + memcpy(out, a.data(), a.size()); + return true; + } + + bool setup(int _dir, int mode, const char *key, int keysize, const char *iv, bool _pad) + { + dir = _dir; + pad = _pad; + type = getType(mode); + r.resize(0); + EVP_CIPHER_CTX_init(&c); + + if(dir == TQCA::Encrypt) { + if(!EVP_EncryptInit(&c, type, NULL, NULL)) + return false; + if(keysize != type->key_len) + EVP_CIPHER_CTX_set_key_length(&c, keysize); + if(!EVP_EncryptInit(&c, NULL, (unsigned char *)key, (unsigned char *)iv)) + return false; + } + else { + if(!EVP_DecryptInit(&c, type, NULL, NULL)) + return false; + if(keysize != type->key_len) + EVP_CIPHER_CTX_set_key_length(&c, keysize); + if(!EVP_DecryptInit(&c, NULL, (unsigned char *)key, (unsigned char *)iv)) + return false; + } + return true; + } + + bool update(const char *in, unsigned int len) + { + TQByteArray result(len + type->block_size); + int olen; + if(dir == TQCA::Encrypt || !pad) { + if(!EVP_EncryptUpdate(&c, (unsigned char *)result.data(), &olen, (unsigned char *)in, len)) + return false; + } + else { + if(!EVP_DecryptUpdate(&c, (unsigned char *)result.data(), &olen, (unsigned char *)in, len)) + return false; + } + result.resize(olen); + appendArray(&r, result); + return true; + } + + bool final(TQByteArray *out) + { + if(pad) { + TQByteArray result(type->block_size); + int olen; + if(dir == TQCA::Encrypt) { + if(!EVP_EncryptFinal(&c, (unsigned char *)result.data(), &olen)) + return false; + } + else { + if(!EVP_DecryptFinal(&c, (unsigned char *)result.data(), &olen)) + return false; + } + result.resize(olen); + appendArray(&r, result); + } + + *out = r.copy(); + r.resize(0); + return true; + } + + EVP_CIPHER_CTX c; + const EVP_CIPHER *type; + TQByteArray r; + int dir; + bool pad; +}; + +class BlowFishContext : public EVPCipherContext +{ +public: + EVPCipherContext *cloneSelf() const { return new BlowFishContext(*this); } + const EVP_CIPHER *getType(int mode) const + { + if(mode == TQCA::CBC) + return EVP_bf_cbc(); + else if(mode == TQCA::CFB) + return EVP_bf_cfb(); + else + return 0; + } +}; + +class TripleDESContext : public EVPCipherContext +{ +public: + EVPCipherContext *cloneSelf() const { return new TripleDESContext(*this); } + const EVP_CIPHER *getType(int mode) const + { + if(mode == TQCA::CBC) + return EVP_des_ede3_cbc(); + else if(mode == TQCA::CFB) + return EVP_des_ede3_cfb(); + else + return 0; + } +}; + +#ifndef NO_AES +class AES128Context : public EVPCipherContext +{ +public: + EVPCipherContext *cloneSelf() const { return new AES128Context(*this); } + const EVP_CIPHER *getType(int mode) const + { + if(mode == TQCA::CBC) + return EVP_aes_128_cbc(); + else if(mode == TQCA::CFB) + return EVP_aes_128_cfb(); + else + return 0; + } +}; + +class AES256Context : public EVPCipherContext +{ +public: + EVPCipherContext *cloneSelf() const { return new AES256Context(*this); } + const EVP_CIPHER *getType(int mode) const + { + if(mode == TQCA::CBC) + return EVP_aes_256_cbc(); + else if(mode == TQCA::CFB) + return EVP_aes_256_cfb(); + else + return 0; + } +}; +#endif + +class RSAKeyContext : public TQCA_RSAKeyContext +{ +public: + RSAKeyContext() + { + pub = 0; + sec = 0; + } + + ~RSAKeyContext() + { + reset(); + } + + void reset() + { + if(pub) { + RSA_free(pub); + pub = 0; + } + if(sec) { + RSA_free(sec); + sec = 0; + } + } + + void separate(RSA *r, RSA **_pub, RSA **_sec) + { + // public + unsigned char *buf, *p; + int len = i2d_RSAPublicKey(r, NULL); + if(len > 0) { + buf = (unsigned char *)malloc(len); + p = buf; + i2d_RSAPublicKey(r, &p); + p = buf; +#ifdef OSSL_097 + *_pub = d2i_RSAPublicKey(NULL, (const unsigned char **)&p, len); +#else + *_pub = d2i_RSAPublicKey(NULL, (unsigned char **)&p, len); +#endif + free(buf); + } + + len = i2d_RSAPrivateKey(r, NULL); + if(len > 0) { + buf = (unsigned char *)malloc(len); + p = buf; + i2d_RSAPrivateKey(r, &p); + p = buf; +#ifdef OSSL_097 + *_sec = d2i_RSAPrivateKey(NULL, (const unsigned char **)&p, len); +#else + *_sec = d2i_RSAPrivateKey(NULL, (unsigned char **)&p, len); +#endif + free(buf); + } + } + + bool isNull() const + { + if(!pub && !sec) + return true; + return false; + } + + bool havePublic() const + { + return pub ? true : false; + } + + bool havePrivate() const + { + return sec ? true : false; + } + + bool createFromDER(const char *in, unsigned int len) + { + RSA *r; + void *p; + + // private? + p = (void *)in; +#ifdef OSSL_097 + r = d2i_RSAPrivateKey(NULL, (const unsigned char **)&p, len); +#else + r = d2i_RSAPrivateKey(NULL, (unsigned char **)&p, len); +#endif + if(r) { + reset(); + + // private means both, I think, so separate them + separate(r, &pub, &sec); + return true; + } + else { + // public? + p = (void *)in; +#ifdef OSSL_097 + r = d2i_RSAPublicKey(NULL, (const unsigned char **)&p, len); +#else + r = d2i_RSAPublicKey(NULL, (unsigned char **)&p, len); +#endif + if(!r) { + // try this other public function, for whatever reason + p = (void *)in; + r = d2i_RSA_PUBKEY(NULL, (const unsigned char **)&p, len); + } + if(r) { + if(pub) { + RSA_free(pub); + } + pub = r; + return true; + } + } + + return false; + } + + bool createFromPEM(const char *in, unsigned int len) + { + BIO *bi; + + // private? + bi = BIO_new(BIO_s_mem()); + BIO_write(bi, in, len); + RSA *r = PEM_read_bio_RSAPrivateKey(bi, NULL, NULL, NULL); + BIO_free(bi); + if(r) { + reset(); + separate(r, &pub, &sec); + return true; + } + else { + // public? + bi = BIO_new(BIO_s_mem()); + BIO_write(bi, in, len); + r = PEM_read_bio_RSAPublicKey(bi, NULL, NULL, NULL); + BIO_free(bi); + if(r) { + if(pub) { + RSA_free(pub); + } + pub = r; + return true; + } + } + + return false; + } + + bool createFromNative(void *in) + { + reset(); + separate((RSA *)in, &pub, &sec); + return true; + } + + bool generate(unsigned int bits) + { + RSA *r = RSA_generate_key(bits, RSA_F4, NULL, NULL); + if(!r) + return false; + separate(r, &pub, &sec); + RSA_free(r); + return true; + } + + TQCA_RSAKeyContext *clone() const + { + // deep copy + RSAKeyContext *c = new RSAKeyContext; + if(pub) { + ++(pub->references); + c->pub = pub; //RSAPublicKey_dup(pub); + } + if(sec) { + ++(sec->references); + c->sec = sec; //RSAPrivateKey_dup(sec); + } + return c; + } + + bool toDER(TQByteArray *out, bool publicOnly) + { + if(sec && !publicOnly) { + int len = i2d_RSAPrivateKey(sec, NULL); + TQByteArray buf(len); + unsigned char *p; + p = (unsigned char *)buf.data(); + i2d_RSAPrivateKey(sec, &p); + *out = buf; + return true; + } + else if(pub) { + int len = i2d_RSAPublicKey(pub, NULL); + TQByteArray buf(len); + unsigned char *p; + p = (unsigned char *)buf.data(); + i2d_RSAPublicKey(pub, &p); + *out = buf; + return true; + } + else + return false; + } + + bool toPEM(TQByteArray *out, bool publicOnly) + { + if(sec && !publicOnly) { + BIO *bo = BIO_new(BIO_s_mem()); + PEM_write_bio_RSAPrivateKey(bo, sec, NULL, NULL, 0, NULL, NULL); + *out = bio2buf(bo); + return true; + } + else if(pub) { + BIO *bo = BIO_new(BIO_s_mem()); + PEM_write_bio_RSAPublicKey(bo, pub); + *out = bio2buf(bo); + return true; + } + else + return false; + + } + + bool encrypt(const TQByteArray &in, TQByteArray *out, bool oaep) + { + if(!pub) + return false; + + int size = RSA_size(pub); + int flen = in.size(); + if(oaep) { + if(flen >= size - 41) + flen = size - 41; + } + else { + if(flen >= size - 11) + flen = size - 11; + } + TQByteArray result(size); + unsigned char *from = (unsigned char *)in.data(); + unsigned char *to = (unsigned char *)result.data(); + int ret = RSA_public_encrypt(flen, from, to, pub, oaep ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING); + if(ret == -1) + return false; + result.resize(ret); + + *out = result; + return true; + } + + bool decrypt(const TQByteArray &in, TQByteArray *out, bool oaep) + { + if(!sec) + return false; + + int size = RSA_size(sec); + int flen = in.size(); + TQByteArray result(size); + unsigned char *from = (unsigned char *)in.data(); + unsigned char *to = (unsigned char *)result.data(); + int ret = RSA_private_decrypt(flen, from, to, sec, oaep ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING); + if(ret == -1) + return false; + result.resize(ret); + + *out = result; + return true; + } + + RSA *pub, *sec; +}; + +static TQValueList nameToProperties(struct X509_name_st *name) +{ + TQValueList list; + + for(int n = 0; n < X509_NAME_entry_count(name); ++n) { + X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, n); + TQCA_CertProperty p; + + ASN1_OBJECT *ao = X509_NAME_ENTRY_get_object(ne); + int nid = OBJ_obj2nid(ao); + if(nid == NID_undef) + continue; + p.var = OBJ_nid2sn(nid); + + ASN1_STRING *as = X509_NAME_ENTRY_get_data(ne); + TQCString c; + c.resize(as->length+1); + strncpy(c.data(), (char *)as->data, as->length); + p.val = TQString::tqfromLatin1(c); + list += p; + } + + return list; +} + +// (taken from kdelibs) -- Justin +// +// This code is mostly taken from OpenSSL v0.9.5a +// by Eric Young +TQDateTime ASN1_UTCTIME_TQDateTime(ASN1_UTCTIME *tm, int *isGmt) +{ + TQDateTime qdt; + char *v; + int gmt=0; + int i; + int y=0,M=0,d=0,h=0,m=0,s=0; + TQDate qdate; + TQTime qtime; + + i = tm->length; + v = (char *)tm->data; + + if (i < 10) goto auq_err; + if (v[i-1] == 'Z') gmt=1; + for (i=0; i<10; i++) + if ((v[i] > '9') || (v[i] < '0')) goto auq_err; + y = (v[0]-'0')*10+(v[1]-'0'); + if (y < 50) y+=100; + M = (v[2]-'0')*10+(v[3]-'0'); + if ((M > 12) || (M < 1)) goto auq_err; + d = (v[4]-'0')*10+(v[5]-'0'); + h = (v[6]-'0')*10+(v[7]-'0'); + m = (v[8]-'0')*10+(v[9]-'0'); + if ( (v[10] >= '0') && (v[10] <= '9') && + (v[11] >= '0') && (v[11] <= '9')) + s = (v[10]-'0')*10+(v[11]-'0'); + + // localize the date and display it. + qdate.setYMD(y+1900, M, d); + qtime.setHMS(h,m,s); + qdt.setDate(qdate); qdt.setTime(qtime); +auq_err: + if (isGmt) *isGmt = gmt; + return qdt; +} + +// (adapted from kdelibs) -- Justin +static bool cnMatchesAddress(const TQString &_cn, const TQString &peerHost) +{ + TQString cn = _cn.stripWhiteSpace().lower(); + TQRegExp rx; + + // Check for invalid characters + if(TQRegExp("[^a-zA-Z0-9\\.\\*\\-]").search(cn) >= 0) + return false; + + // Domains can legally end with '.'s. We don't need them though. + while(cn.endsWith(".")) + cn.truncate(cn.length()-1); + + // Do not let empty CN's get by!! + if(cn.isEmpty()) + return false; + + // Check for IPv4 address + rx.setPattern("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"); + if(rx.exactMatch(peerHost)) + return peerHost == cn; + + // Check for IPv6 address here... + rx.setPattern("^\\[.*\\]$"); + if(rx.exactMatch(peerHost)) + return peerHost == cn; + + if(cn.contains('*')) { + // First make sure that there are at least two valid parts + // after the wildcard (*). + TQStringList parts = TQStringList::split('.', cn, false); + + while(parts.count() > 2) + parts.remove(parts.begin()); + + if(parts.count() != 2) { + return false; // we don't allow *.root - that's bad + } + + if(parts[0].contains('*') || parts[1].contains('*')) { + return false; + } + + // RFC2818 says that *.example.com should match against + // foo.example.com but not bar.foo.example.com + // (ie. they must have the same number of parts) + if(TQRegExp(cn, false, true).exactMatch(peerHost) && + TQStringList::split('.', cn, false).count() == + TQStringList::split('.', peerHost, false).count()) + return true; + + return false; + } + + // We must have an exact match in this case (insensitive though) + // (note we already did .lower()) + if(cn == peerHost) + return true; + return false; +} + +class CertContext : public TQCA_CertContext +{ +public: + CertContext() + { + x = 0; + } + + ~CertContext() + { + reset(); + } + + TQCA_CertContext *clone() const + { + CertContext *c = new CertContext(*this); + if(x) { + ++(x->references); + c->x = x; + } + return c; + } + + void reset() + { + if(x) { + X509_free(x); + x = 0; + + serial = ""; + v_subject = ""; + v_issuer = ""; + cp_subject.clear(); + cp_issuer.clear(); + na = TQDateTime(); + nb = TQDateTime(); + } + } + + bool isNull() const + { + return (x ? false: true); + } + + bool createFromDER(const char *in, unsigned int len) + { + const unsigned char *p = (const unsigned char *)in; + X509 *t = d2i_X509(NULL, &p, len); + if(!t) + return false; + fromX509(t); + X509_free(t); + return true; + } + + bool createFromPEM(const char *in, unsigned int len) + { + BIO *bi = BIO_new(BIO_s_mem()); + BIO_write(bi, in, len); + X509 *t = PEM_read_bio_X509(bi, NULL, NULL, NULL); + BIO_free(bi); + if(!t) + return false; + fromX509(t); + X509_free(t); + return true; + } + + bool toDER(TQByteArray *out) + { + int len = i2d_X509(x, NULL); + TQByteArray buf(len); + unsigned char *p = (unsigned char *)buf.data(); + i2d_X509(x, &p); + *out = buf; + return true; + } + + bool toPEM(TQByteArray *out) + { + BIO *bo = BIO_new(BIO_s_mem()); + PEM_write_bio_X509(bo, x); + *out = bio2buf(bo); + return true; + } + + void fromX509(X509 *t) + { + reset(); + ++(t->references); + x = t; + + // serial number + ASN1_INTEGER *ai = X509_get_serialNumber(x); + if(ai) { + char *rep = i2s_ASN1_INTEGER(NULL, ai); + serial = rep; + OPENSSL_free(rep); + } + + // validity dates + nb = ASN1_UTCTIME_TQDateTime(X509_get_notBefore(x), NULL); + na = ASN1_UTCTIME_TQDateTime(X509_get_notAfter(x), NULL); + + // extract the subject/issuer strings + struct X509_name_st *sn = X509_get_subject_name(x); + struct X509_name_st *in = X509_get_issuer_name(x); + char buf[1024]; + X509_NAME_oneline(sn, buf, 1024); + v_subject = buf; + X509_NAME_oneline(in, buf, 1024); + v_issuer = buf; + + // extract the subject/issuer contents + cp_subject = nameToProperties(sn); + cp_issuer = nameToProperties(in); + } + + TQString serialNumber() const + { + return serial; + } + + TQString subjectString() const + { + return v_subject; + } + + TQString issuerString() const + { + return v_issuer; + } + + TQValueList subject() const + { + return cp_subject; + } + + TQValueList issuer() const + { + return cp_issuer; + } + + TQDateTime notBefore() const + { + return nb; + } + + TQDateTime notAfter() const + { + return na; + } + + bool matchesAddress(const TQString &realHost) const + { + TQString peerHost = realHost.stripWhiteSpace(); + while(peerHost.endsWith(".")) + peerHost.truncate(peerHost.length()-1); + peerHost = peerHost.lower(); + + TQString cn; + for(TQValueList::ConstIterator it = cp_subject.begin(); it != cp_subject.end(); ++it) { + if((*it).var == "CN") { + cn = (*it).val; + break; + } + } + if(cnMatchesAddress(cn, peerHost)) + return true; + return false; + } + + X509 *x; + TQString serial, v_subject, v_issuer; + TQValueList cp_subject, cp_issuer; + TQDateTime nb, na; +}; + +static bool ssl_init = false; +class TLSContext : public TQCA_TLSContext +{ +public: + enum { Good, TryAgain, Bad }; + enum { Idle, Connect, Accept, Handshake, Active, Closing }; + + bool serv; + int mode; + TQByteArray sendQueue, recvQueue; + + CertContext *cert; + RSAKeyContext *key; + + SSL *ssl; + SSL_METHOD *method; + SSL_CTX *context; + BIO *rbio, *wbio; + CertContext cc; + int vr; + bool v_eof; + + TLSContext() + { + if(!ssl_init) { + SSL_library_init(); + SSL_load_error_strings(); + ssl_init = true; + } + + ssl = 0; + context = 0; + cert = 0; + key = 0; + } + + ~TLSContext() + { + reset(); + } + + void reset() + { + if(ssl) { + SSL_free(ssl); + ssl = 0; + } + if(context) { + SSL_CTX_free(context); + context = 0; + } + if(cert) { + delete cert; + cert = 0; + } + if(key) { + delete key; + key = 0; + } + + sendQueue.resize(0); + recvQueue.resize(0); + mode = Idle; + cc.reset(); + vr = TQCA::TLS::Unknown; + v_eof = false; + } + + bool eof() const + { + return v_eof; + } + + bool startClient(const TQPtrList &store, const TQCA_CertContext &_cert, const TQCA_RSAKeyContext &_key) + { + reset(); + serv = false; + method = const_cast(SSLv23_client_method()); + + if(!setup(store, _cert, _key)) + return false; + + mode = Connect; + return true; + } + + bool startServer(const TQPtrList &store, const TQCA_CertContext &_cert, const TQCA_RSAKeyContext &_key) + { + reset(); + serv = true; + method = const_cast(SSLv23_server_method()); + + if(!setup(store, _cert, _key)) + return false; + + mode = Accept; + return true; + } + + bool setup(const TQPtrList &list, const TQCA_CertContext &_cc, const TQCA_RSAKeyContext &kc) + { + context = SSL_CTX_new(method); + if(!context) { + reset(); + return false; + } + + // load the cert store + if(!list.isEmpty()) { + X509_STORE *store = SSL_CTX_get_cert_store(context); + TQPtrListIterator it(list); + for(CertContext *i; (i = (CertContext *)it.current()); ++it) + X509_STORE_add_cert(store, i->x); + } + + ssl = SSL_new(context); + if(!ssl) { + reset(); + return false; + } + SSL_set_ssl_method(ssl, method); // can this return error? + + // setup the memory bio + rbio = BIO_new(BIO_s_mem()); + wbio = BIO_new(BIO_s_mem()); + + // this passes control of the bios to ssl. we don't need to free them. + SSL_set_bio(ssl, rbio, wbio); + + // setup the cert to send + if(!_cc.isNull() && !kc.isNull()) { + cert = static_cast(_cc.clone()); + key = static_cast(kc.clone()); + if(SSL_use_certificate(ssl, cert->x) != 1) { + reset(); + return false; + } + if(SSL_use_RSAPrivateKey(ssl, key->sec) != 1) { + reset(); + return false; + } + } + + return true; + } + + int handshake(const TQByteArray &in, TQByteArray *out) + { + if(!in.isEmpty()) + BIO_write(rbio, in.data(), in.size()); + + if(mode == Connect) { + int ret = doConnect(); + if(ret == Good) { + mode = Handshake; + } + else if(ret == Bad) { + reset(); + return Error; + } + } + + if(mode == Accept) { + int ret = doAccept(); + if(ret == Good) { + getCert(); + mode = Active; + } + else if(ret == Bad) { + reset(); + return Error; + } + } + + if(mode == Handshake) { + int ret = doHandshake(); + if(ret == Good) { + getCert(); + mode = Active; + } + else if(ret == Bad) { + reset(); + return Error; + } + } + + // process outgoing + *out = readOutgoing(); + + if(mode == Active) + return Success; + else + return Continue; + } + + int shutdown(const TQByteArray &in, TQByteArray *out) + { + if(!in.isEmpty()) + BIO_write(rbio, in.data(), in.size()); + + int ret = doShutdown(); + if(ret == Bad) { + reset(); + return Error; + } + + *out = readOutgoing(); + + if(ret == Good) { + mode = Idle; + return Success; + } + else { + mode = Closing; + return Continue; + } + } + + void getCert() + { + // verify the certificate + int code = TQCA::TLS::Unknown; + X509 *x = SSL_get_peer_certificate(ssl); + if(x) { + cc.fromX509(x); + X509_free(x); + int ret = SSL_get_verify_result(ssl); + if(ret == X509_V_OK) + code = TQCA::TLS::Valid; + else + code = resultToCV(ret); + } + else { + cc.reset(); + code = TQCA::TLS::NoCert; + } + vr = code; + } + + bool encode(const TQByteArray &plain, TQByteArray *to_net, int *enc) + { + if(mode != Active) + return false; + appendArray(&sendQueue, plain); + + int encoded = 0; + if(sendQueue.size() > 0) { + int ret = SSL_write(ssl, sendQueue.data(), sendQueue.size()); + + enum { Good, Continue, Done, Error }; + int m; + if(ret <= 0) { + int x = SSL_get_error(ssl, ret); + if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE) + m = Continue; + else if(x == SSL_ERROR_ZERO_RETURN) + m = Done; + else + m = Error; + } + else { + m = Good; + encoded = ret; + int newsize = sendQueue.size() - encoded; + char *r = sendQueue.data(); + memmove(r, r + encoded, newsize); + sendQueue.resize(newsize); + } + + if(m == Done) { + sendQueue.resize(0); + v_eof = true; + return false; + } + if(m == Error) { + sendQueue.resize(0); + return false; + } + } + + *to_net = readOutgoing(); + *enc = encoded; + return true; + } + + bool decode(const TQByteArray &from_net, TQByteArray *plain, TQByteArray *to_net) + { + if(mode != Active) + return false; + if(!from_net.isEmpty()) + BIO_write(rbio, from_net.data(), from_net.size()); + + TQByteArray a; + while(!v_eof) { + a.resize(8192); + int ret = SSL_read(ssl, a.data(), a.size()); + if(ret > 0) { + if(ret != (int)a.size()) + a.resize(ret); + appendArray(&recvQueue, a); + } + else if(ret <= 0) { + int x = SSL_get_error(ssl, ret); + if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE) + break; + else if(x == SSL_ERROR_ZERO_RETURN) + v_eof = true; + else + return false; + } + } + + *plain = recvQueue.copy(); + recvQueue.resize(0); + + // could be outgoing data also + *to_net = readOutgoing(); + return true; + } + + TQByteArray unprocessed() + { + TQByteArray a; + int size = BIO_pending(rbio); + if(size <= 0) + return a; + a.resize(size); + + int r = BIO_read(rbio, a.data(), size); + if(r <= 0) { + a.resize(0); + return a; + } + if(r != size) + a.resize(r); + return a; + } + + TQByteArray readOutgoing() + { + TQByteArray a; + int size = BIO_pending(wbio); + if(size <= 0) + return a; + a.resize(size); + + int r = BIO_read(wbio, a.data(), size); + if(r <= 0) { + a.resize(0); + return a; + } + if(r != size) + a.resize(r); + return a; + } + + int doConnect() + { + int ret = SSL_connect(ssl); + if(ret < 0) { + int x = SSL_get_error(ssl, ret); + if(x == SSL_ERROR_WANT_CONNECT || x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE) + return TryAgain; + else + return Bad; + } + else if(ret == 0) + return Bad; + return Good; + } + + int doAccept() + { + int ret = SSL_accept(ssl); + if(ret < 0) { + int x = SSL_get_error(ssl, ret); + if(x == SSL_ERROR_WANT_CONNECT || x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE) + return TryAgain; + else + return Bad; + } + else if(ret == 0) + return Bad; + return Good; + } + + int doHandshake() + { + int ret = SSL_do_handshake(ssl); + if(ret < 0) { + int x = SSL_get_error(ssl, ret); + if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE) + return TryAgain; + else + return Bad; + } + else if(ret == 0) + return Bad; + return Good; + } + + int doShutdown() + { + int ret = SSL_shutdown(ssl); + if(ret >= 1) + return Good; + else { + if(ret == 0) + return TryAgain; + int x = SSL_get_error(ssl, ret); + if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE) + return TryAgain; + return Bad; + } + } + + TQCA_CertContext *peerCertificate() const + { + return cc.clone(); + } + + int validityResult() const + { + return vr; + } + + int resultToCV(int ret) const + { + int rc; + + switch(ret) { + case X509_V_ERR_CERT_REJECTED: + rc = TQCA::TLS::Rejected; + break; + case X509_V_ERR_CERT_UNTRUSTED: + rc = TQCA::TLS::Untrusted; + break; + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + rc = TQCA::TLS::SignatureFailed; + break; + case X509_V_ERR_INVALID_CA: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + rc = TQCA::TLS::InvalidCA; + break; + case X509_V_ERR_INVALID_PURPOSE: + rc = TQCA::TLS::InvalidPurpose; + break; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + rc = TQCA::TLS::SelfSigned; + break; + case X509_V_ERR_CERT_REVOKED: + rc = TQCA::TLS::Revoked; + break; + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + rc = TQCA::TLS::PathLengthExceeded; + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CRL_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + rc = TQCA::TLS::Expired; + break; + case X509_V_ERR_APPLICATION_VERIFICATION: + case X509_V_ERR_OUT_OF_MEM: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + default: + rc = TQCA::TLS::Unknown; + break; + } + return rc; + } +}; + +class TQCAOpenSSL : public TQCAProvider +{ +public: + TQCAOpenSSL() {} + ~TQCAOpenSSL() {} + + void init() + { + } + + int qcaVersion() const + { + return TQCA_PLUGIN_VERSION; + } + + int capabilities() const + { + int caps = + TQCA::CAP_SHA1 | + TQCA::CAP_MD5 | + TQCA::CAP_BlowFish | + TQCA::CAP_TripleDES | +#ifndef NO_AES + TQCA::CAP_AES128 | + TQCA::CAP_AES256 | +#endif + TQCA::CAP_RSA | + TQCA::CAP_X509 | + TQCA::CAP_TLS; + return caps; + } + + void *context(int cap) + { + if(cap == TQCA::CAP_SHA1) + return new SHA1Context; + else if(cap == TQCA::CAP_MD5) + return new MD5Context; + else if(cap == TQCA::CAP_BlowFish) + return new BlowFishContext; + else if(cap == TQCA::CAP_TripleDES) + return new TripleDESContext; +#ifndef NO_AES + else if(cap == TQCA::CAP_AES128) + return new AES128Context; + else if(cap == TQCA::CAP_AES256) + return new AES256Context; +#endif + else if(cap == TQCA::CAP_RSA) + return new RSAKeyContext; + else if(cap == TQCA::CAP_X509) + return new CertContext; + else if(cap == TQCA::CAP_TLS) + return new TLSContext; + return 0; + } +}; + +#ifdef TQCA_PLUGIN +TQCAProvider *createProvider() +#else +TQCAProvider *createProviderTLS() +#endif +{ + return (new TQCAOpenSSL); +} diff --git a/qca-tls.h b/qca-tls.h new file mode 100644 index 0000000..1594492 --- /dev/null +++ b/qca-tls.h @@ -0,0 +1,32 @@ +/* + * qca-tls.h - TLS plugin for TQCA + * Copyright (C) 2003 Justin Karneges + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef TQCA_TLS_H +#define TQCA_TLS_H + +#include"qcaprovider.h" + +#ifdef TQCA_PLUGIN +TQCA_PLUGIN_EXPORT TQCAProvider *createProvider(); +#else +TQCAProvider *createProviderTLS(); +#endif + +#endif diff --git a/qca-tls.pro b/qca-tls.pro new file mode 100644 index 0000000..c1541bf --- /dev/null +++ b/qca-tls.pro @@ -0,0 +1,26 @@ +# qca-tls qmake profile + +TEMPLATE = lib +CONFIG += qt thread release plugin +TARGET = qca-tls + +!exists(qcaprovider.h) { + Q_PREFIX = ../../src + INCLUDEPATH += $$Q_PREFIX +} +HEADERS += ($$Q_PREFIX)qcaprovider.h + +HEADERS = qca-tls.h +SOURCES = qca-tls.cpp + +DEFINES += QCA_PLUGIN +win32:{ + DEFINES += QCA_PLUGIN_DLL OSSL_097 + INCLUDEPATH += c:\local\include + LIBS += c:\local\lib\libeay32.lib c:\local\lib\ssleay32.lib +} + +include(conf.pri) +include(extra.pri) + +QMAKE_PROJECT_DEPTH=0 diff --git a/qca-tls.qc b/qca-tls.qc new file mode 100644 index 0000000..ef0a739 --- /dev/null +++ b/qca-tls.qc @@ -0,0 +1,9 @@ + + qca-tls + qca-tls.pro + + + + + . + diff --git a/qca.h b/qca.h new file mode 100644 index 0000000..8f42d61 --- /dev/null +++ b/qca.h @@ -0,0 +1,468 @@ +/* + * qca.h - TQt Cryptographic Architecture + * Copyright (C) 2003 Justin Karneges + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef TQCA_H +#define TQCA_H + +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_WIN32 +# ifndef TQCA_STATIC +# ifdef TQCA_MAKEDLL +# define TQCA_EXPORT __declspec(dllexport) +# else +# define TQCA_EXPORT __declspec(dllimport) +# endif +# endif +#endif +#ifndef TQCA_EXPORT +#define TQCA_EXPORT +#endif + +#ifdef Q_OS_WIN32 +# ifdef TQCA_PLUGIN_DLL +# define TQCA_PLUGIN_EXPORT extern "C" __declspec(dllexport) +# else +# define TQCA_PLUGIN_EXPORT extern "C" __declspec(dllimport) +# endif +#endif +#ifndef TQCA_PLUGIN_EXPORT +#define TQCA_PLUGIN_EXPORT extern "C" +#endif + +class TQHostAddress; +class TQStringList; + +class TQCAProvider; +class TQCA_HashContext; +class TQCA_CipherContext; +class TQCA_CertContext; + +namespace TQCA +{ + enum { + CAP_SHA1 = 0x0001, + CAP_SHA256 = 0x0002, + CAP_MD5 = 0x0004, + CAP_BlowFish = 0x0008, + CAP_TripleDES = 0x0010, + CAP_AES128 = 0x0020, + CAP_AES256 = 0x0040, + CAP_RSA = 0x0080, + CAP_X509 = 0x0100, + CAP_TLS = 0x0200, + CAP_SASL = 0x0400 + }; + + enum { + CBC = 0x0001, + CFB = 0x0002 + }; + + enum { + Encrypt = 0x0001, + Decrypt = 0x0002 + }; + + TQCA_EXPORT void init(); + TQCA_EXPORT bool isSupported(int capabilities); + TQCA_EXPORT void insertProvider(TQCAProvider *); + TQCA_EXPORT void unloadAllPlugins(); + + TQCA_EXPORT TQString arrayToHex(const TQByteArray &); + TQCA_EXPORT TQByteArray hexToArray(const TQString &); + + class TQCA_EXPORT Hash + { + public: + Hash(const Hash &); + Hash & operator=(const Hash &); + ~Hash(); + + void clear(); + void update(const TQByteArray &a); + TQByteArray final(); + + protected: + Hash(TQCA_HashContext *); + + private: + class Private; + Private *d; + }; + + template + class TQCA_EXPORT HashStatic + { + public: + HashStatic() {} + + static TQByteArray hash(const TQByteArray &a) + { + T obj; + obj.update(a); + return obj.final(); + } + + static TQByteArray hash(const TQCString &cs) + { + TQByteArray a(cs.length()); + memcpy(a.data(), cs.data(), a.size()); + return hash(a); + } + + static TQString hashToString(const TQByteArray &a) + { + return arrayToHex(hash(a)); + } + + static TQString hashToString(const TQCString &cs) + { + return arrayToHex(hash(cs)); + } + }; + + class TQCA_EXPORT Cipher + { + public: + Cipher(const Cipher &); + Cipher & operator=(const Cipher &); + ~Cipher(); + + TQByteArray dyn_generateKey(int size=-1) const; + TQByteArray dyn_generateIV() const; + void reset(int dir, int mode, const TQByteArray &key, const TQByteArray &iv, bool pad=true); + bool update(const TQByteArray &a); + TQByteArray final(bool *ok=0); + + protected: + Cipher(TQCA_CipherContext *, int dir, int mode, const TQByteArray &key, const TQByteArray &iv, bool pad); + + private: + class Private; + Private *d; + }; + + template + class TQCA_EXPORT CipherStatic + { + public: + CipherStatic() {} + + static TQByteArray generateKey(int size=-1) + { + T obj; + return obj.dyn_generateKey(size); + } + + static TQByteArray generateIV() + { + T obj; + return obj.dyn_generateIV(); + } + }; + + class TQCA_EXPORT SHA1 : public Hash, public HashStatic + { + public: + SHA1(); + }; + + class TQCA_EXPORT SHA256 : public Hash, public HashStatic + { + public: + SHA256(); + }; + + class TQCA_EXPORT MD5 : public Hash, public HashStatic + { + public: + MD5(); + }; + + class TQCA_EXPORT BlowFish : public Cipher, public CipherStatic + { + public: + BlowFish(int dir=Encrypt, int mode=CBC, const TQByteArray &key=TQByteArray(), const TQByteArray &iv=TQByteArray(), bool pad=true); + }; + + class TQCA_EXPORT TripleDES : public Cipher, public CipherStatic + { + public: + TripleDES(int dir=Encrypt, int mode=CBC, const TQByteArray &key=TQByteArray(), const TQByteArray &iv=TQByteArray(), bool pad=true); + }; + + class TQCA_EXPORT AES128 : public Cipher, public CipherStatic + { + public: + AES128(int dir=Encrypt, int mode=CBC, const TQByteArray &key=TQByteArray(), const TQByteArray &iv=TQByteArray(), bool pad=true); + }; + + class TQCA_EXPORT AES256 : public Cipher, public CipherStatic + { + public: + AES256(int dir=Encrypt, int mode=CBC, const TQByteArray &key=TQByteArray(), const TQByteArray &iv=TQByteArray(), bool pad=true); + }; + + class RSA; + class TQCA_EXPORT RSAKey + { + public: + RSAKey(); + RSAKey(const RSAKey &from); + RSAKey & operator=(const RSAKey &from); + ~RSAKey(); + + bool isNull() const; + bool havePublic() const; + bool havePrivate() const; + + TQByteArray toDER(bool publicOnly=false) const; + bool fromDER(const TQByteArray &a); + + TQString toPEM(bool publicOnly=false) const; + bool fromPEM(const TQString &); + + // only call if you know what you are doing + bool fromNative(void *); + + private: + class Private; + Private *d; + + friend class RSA; + friend class TLS; + bool encrypt(const TQByteArray &a, TQByteArray *out, bool oaep) const; + bool decrypt(const TQByteArray &a, TQByteArray *out, bool oaep) const; + bool generate(unsigned int bits); + }; + + class TQCA_EXPORT RSA + { + public: + RSA(); + ~RSA(); + + RSAKey key() const; + void setKey(const RSAKey &); + + bool encrypt(const TQByteArray &a, TQByteArray *out, bool oaep=false) const; + bool decrypt(const TQByteArray &a, TQByteArray *out, bool oaep=false) const; + + static RSAKey generateKey(unsigned int bits); + + private: + RSAKey v_key; + }; + + typedef TQMap CertProperties; + class TQCA_EXPORT Cert + { + public: + Cert(); + Cert(const Cert &); + Cert & operator=(const Cert &); + ~Cert(); + + bool isNull() const; + + TQString commonName() const; + TQString serialNumber() const; + TQString subjectString() const; + TQString issuerString() const; + CertProperties subject() const; + CertProperties issuer() const; + TQDateTime notBefore() const; + TQDateTime notAfter() const; + + TQByteArray toDER() const; + bool fromDER(const TQByteArray &a); + + TQString toPEM() const; + bool fromPEM(const TQString &); + + private: + class Private; + Private *d; + + friend class TLS; + void fromContext(TQCA_CertContext *); + }; + + class TQCA_EXPORT TLS : public TQObject + { + Q_OBJECT + TQ_OBJECT + public: + enum Validity { + NoCert, + Valid, + HostMismatch, + Rejected, + Untrusted, + SignatureFailed, + InvalidCA, + InvalidPurpose, + SelfSigned, + Revoked, + PathLengthExceeded, + Expired, + Unknown + }; + enum Error { ErrHandshake, ErrCrypt }; + + TLS(TQObject *parent=0); + ~TLS(); + + void setCertificate(const Cert &cert, const RSAKey &key); + void setCertificateStore(const TQPtrList &store); // note: store must persist + + void reset(); + bool startClient(const TQString &host=""); + bool startServer(); + void close(); + bool isHandshaken() const; + + // plain (application side) + void write(const TQByteArray &a); + TQByteArray read(); + + // encoded (socket side) + void writeIncoming(const TQByteArray &a); + TQByteArray readOutgoing(); + TQByteArray readUnprocessed(); + + // cert related + const Cert & peerCertificate() const; + int certificateValidityResult() const; + + signals: + void handshaken(); + void readyRead(); + void readyReadOutgoing(int plainBytes); + void closed(); + void error(int); + + private slots: + void update(); + + private: + class Private; + Private *d; + }; + + class TQCA_EXPORT SASL : public TQObject + { + Q_OBJECT + TQ_OBJECT + public: + enum Error { ErrAuth, ErrCrypt }; + enum ErrorCond { + NoMech, + BadProto, + BadServ, + BadAuth, + NoAuthzid, + TooWeak, + NeedEncrypt, + Expired, + Disabled, + NoUser, + RemoteUnavail + }; + SASL(TQObject *parent=0); + ~SASL(); + + static void setAppName(const TQString &name); + + void reset(); + int errorCondition() const; + + // options + void setAllowPlain(bool); + void setAllowAnonymous(bool); + void setAllowActiveVulnerable(bool); + void setAllowDictionaryVulnerable(bool); + void setRequireForwardSecrecy(bool); + void setRequirePassCredentials(bool); + void setRequireMutualAuth(bool); + + void setMinimumSSF(int); + void setMaximumSSF(int); + void setExternalAuthID(const TQString &authid); + void setExternalSSF(int); + + void setLocalAddr(const TQHostAddress &addr, TQ_UINT16 port); + void setRemoteAddr(const TQHostAddress &addr, TQ_UINT16 port); + + // initialize + bool startClient(const TQString &service, const TQString &host, const TQStringList &mechlist, bool allowClientSendFirst=true); + bool startServer(const TQString &service, const TQString &host, const TQString &realm, TQStringList *mechlist); + + // authentication + void putStep(const TQByteArray &stepData); + void putServerFirstStep(const TQString &mech); + void putServerFirstStep(const TQString &mech, const TQByteArray &clientInit); + void setUsername(const TQString &user); + void setAuthzid(const TQString &auth); + void setPassword(const TQString &pass); + void setRealm(const TQString &realm); + void continueAfterParams(); + void continueAfterAuthCheck(); + + // security layer + int ssf() const; + void write(const TQByteArray &a); + TQByteArray read(); + void writeIncoming(const TQByteArray &a); + TQByteArray readOutgoing(); + + signals: + // for authentication + void clientFirstStep(const TQString &mech, const TQByteArray *clientInit); + void nextStep(const TQByteArray &stepData); + void needParams(bool user, bool authzid, bool pass, bool realm); + void authCheck(const TQString &user, const TQString &authzid); + void authenticated(); + + // for security layer + void readyRead(); + void readyReadOutgoing(int plainBytes); + + // error + void error(int); + + private slots: + void tryAgain(); + + private: + class Private; + Private *d; + + void handleServerFirstStep(int r); + }; +}; + +#endif diff --git a/qcaprovider.h b/qcaprovider.h new file mode 100644 index 0000000..46c06c5 --- /dev/null +++ b/qcaprovider.h @@ -0,0 +1,191 @@ +/* + * qcaprovider.h - TQCA Plugin API + * Copyright (C) 2003 Justin Karneges + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef TQCAPROVIDER_H +#define TQCAPROVIDER_H + +#include +#include +#include +#include +#include +#include"qca.h" + +#define TQCA_PLUGIN_VERSION 1 + +class TQCAProvider +{ +public: + TQCAProvider() {} + virtual ~TQCAProvider() {} + + virtual void init()=0; + virtual int qcaVersion() const=0; + virtual int capabilities() const=0; + virtual void *context(int cap)=0; +}; + +class TQCA_HashContext +{ +public: + virtual ~TQCA_HashContext() {} + + virtual TQCA_HashContext *clone()=0; + virtual void reset()=0; + virtual void update(const char *in, unsigned int len)=0; + virtual void final(TQByteArray *out)=0; +}; + +class TQCA_CipherContext +{ +public: + virtual ~TQCA_CipherContext() {} + + virtual TQCA_CipherContext *clone()=0; + virtual int keySize()=0; + virtual int blockSize()=0; + virtual bool generateKey(char *out, int keysize=-1)=0; + virtual bool generateIV(char *out)=0; + + virtual bool setup(int dir, int mode, const char *key, int keysize, const char *iv, bool pad)=0; + virtual bool update(const char *in, unsigned int len)=0; + virtual bool final(TQByteArray *out)=0; +}; + +class TQCA_RSAKeyContext +{ +public: + virtual ~TQCA_RSAKeyContext() {} + + virtual TQCA_RSAKeyContext *clone() const=0; + virtual bool isNull() const=0; + virtual bool havePublic() const=0; + virtual bool havePrivate() const=0; + virtual bool createFromDER(const char *in, unsigned int len)=0; + virtual bool createFromPEM(const char *in, unsigned int len)=0; + virtual bool createFromNative(void *in)=0; + virtual bool generate(unsigned int bits)=0; + virtual bool toDER(TQByteArray *out, bool publicOnly)=0; + virtual bool toPEM(TQByteArray *out, bool publicOnly)=0; + + virtual bool encrypt(const TQByteArray &in, TQByteArray *out, bool oaep)=0; + virtual bool decrypt(const TQByteArray &in, TQByteArray *out, bool oaep)=0; +}; + +struct TQCA_CertProperty +{ + TQString var; + TQString val; +}; + +class TQCA_CertContext +{ +public: + virtual ~TQCA_CertContext() {} + + virtual TQCA_CertContext *clone() const=0; + virtual bool isNull() const=0; + virtual bool createFromDER(const char *in, unsigned int len)=0; + virtual bool createFromPEM(const char *in, unsigned int len)=0; + virtual bool toDER(TQByteArray *out)=0; + virtual bool toPEM(TQByteArray *out)=0; + + virtual TQString serialNumber() const=0; + virtual TQString subjectString() const=0; + virtual TQString issuerString() const=0; + virtual TQValueList subject() const=0; + virtual TQValueList issuer() const=0; + virtual TQDateTime notBefore() const=0; + virtual TQDateTime notAfter() const=0; + virtual bool matchesAddress(const TQString &realHost) const=0; +}; + +class TQCA_TLSContext +{ +public: + enum Result { Success, Error, Continue }; + virtual ~TQCA_TLSContext() {} + + virtual void reset()=0; + virtual bool startClient(const TQPtrList &store, const TQCA_CertContext &cert, const TQCA_RSAKeyContext &key)=0; + virtual bool startServer(const TQPtrList &store, const TQCA_CertContext &cert, const TQCA_RSAKeyContext &key)=0; + + virtual int handshake(const TQByteArray &in, TQByteArray *out)=0; + virtual int shutdown(const TQByteArray &in, TQByteArray *out)=0; + virtual bool encode(const TQByteArray &plain, TQByteArray *to_net, int *encoded)=0; + virtual bool decode(const TQByteArray &from_net, TQByteArray *plain, TQByteArray *to_net)=0; + virtual bool eof() const=0; + virtual TQByteArray unprocessed()=0; + + virtual TQCA_CertContext *peerCertificate() const=0; + virtual int validityResult() const=0; +}; + +struct TQCA_SASLHostPort +{ + TQHostAddress addr; + TQ_UINT16 port; +}; + +struct TQCA_SASLNeedParams +{ + bool user, authzid, pass, realm; +}; + +class TQCA_SASLContext +{ +public: + enum Result { Success, Error, NeedParams, AuthCheck, Continue }; + virtual ~TQCA_SASLContext() {} + + // common + virtual void reset()=0; + virtual void setCoreProps(const TQString &service, const TQString &host, TQCA_SASLHostPort *local, TQCA_SASLHostPort *remote)=0; + virtual void setSecurityProps(bool noPlain, bool noActive, bool noDict, bool noAnon, bool reqForward, bool reqCreds, bool reqMutual, int ssfMin, int ssfMax, const TQString &_ext_authid, int _ext_ssf)=0; + virtual int security() const=0; + virtual int errorCond() const=0; + + // init / first step + virtual bool clientStart(const TQStringList &mechlist)=0; + virtual int clientFirstStep(bool allowClientSendFirst)=0; + virtual bool serverStart(const TQString &realm, TQStringList *mechlist, const TQString &name)=0; + virtual int serverFirstStep(const TQString &mech, const TQByteArray *in)=0; + + // get / set params + virtual TQCA_SASLNeedParams clientParamsNeeded() const=0; + virtual void setClientParams(const TQString *user, const TQString *authzid, const TQString *pass, const TQString *realm)=0; + virtual TQString username() const=0; + virtual TQString authzid() const=0; + + // continue steps + virtual int nextStep(const TQByteArray &in)=0; + virtual int tryAgain()=0; + + // results + virtual TQString mech() const=0; + virtual const TQByteArray *clientInit() const=0; + virtual TQByteArray result() const=0; + + // security layer + virtual bool encode(const TQByteArray &in, TQByteArray *out)=0; + virtual bool decode(const TQByteArray &in, TQByteArray *out)=0; +}; + +#endif diff --git a/qcextra b/qcextra new file mode 100755 index 0000000..fef4f18 --- /dev/null +++ b/qcextra @@ -0,0 +1,9 @@ +#!/bin/sh + +cat >extra.pri <