commit f81dd6669856792aba1177ef3179d0d1718b7f68 Author: root Date: Tue Feb 28 08:23:39 2012 +0000 Initial import of 0.83 from SF diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..cdd32a2 --- /dev/null +++ b/.htaccess @@ -0,0 +1,6 @@ +-e Options FollowSymLinks +-e php_flag register_globals off +-e php_flag register_long_arrays on +-e AddType application/x-x509-ca-cert .crt .pem +-e AddType application/pkix-crl .crl +-e AddType application/pkix-cert .cer .der diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..2a26e51 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,129 @@ +v0.01: 03-Mar-21: +- Limited preview release. + +v0.02: 03-Mar-22: +- Improved user fiendliness of some terminology. +- Added Unit column to, removed serial column from control panel. +- Added Makefile to make distclean for distribution. +- Improved installation/setup automation with PHP setup script, Makefile + and secure.sh script. +- Added support for NetscapeRevocationURL protocol. +- Minor fixes. +- Minor help file changes. + +v0.03: +- Added System Admin module under ca/admin for creating adding/removing users + and updating CRL. +- Fixed NetscapeRevocationURL malformed URL (was missing '?' at end of URL) +- Revoked certificates can now be found with public search, but cannot be + downloaded. Certificate status is shown. +- Added authorityInfoAccess extension to certificates. +- All forms should now load with cursor focus in first field. +- E-mail addresses are now clickable "mailto:" links. +- Added sample crontab CRL update script for use with RedHat style + /etc/cron.monthly crontab layout. +- Probably some minor bug fixes not worth listing separately. +- Updated HELP screenshots + +v0.04: +- Fixed a download problem which could cause corrupted certificates and + CRLs. The upload() function was using fpassthru() which automatically + closes the file. A subsequent fclose() error was adding extra junk to + the end of downloads. Switched to readfile(). +- Added end-user help screens. More to come. + A brief explanation of PKI and e-mail encryption. + Root certificate installation for Outlook/Express + Personal e-mail certificate installation for Outlook/Express +- Some tweaking of certificate downloads to be more Netscape friendly. +- Some clean-up and reorganization of files, directories, and symlinks. + +v0.05 +- Added cert status filter to end-user search. +- Cleaned up some double/single quoting. +- SECURITY: Using escapeshellarg() throughout openssl_functions. +- SECURITY: gpvar() adds slashes if magic_quotes_gpc is disabled. + +v0.06 +- Added EXPERIMENTAL Web server certificate support. +- Added practices & policy statements +- Added descriptions to menu selections. +- SECURITY: Tightened permissions set by secure.sh script. +- SECURITY: Fixed insecure temp file creation in create_user_cnf(). + +v0.60 +- Shifted version number left one digit to signify move to BETA status. + +v0.70 +- Fixed various typographical errors. +- Fixed updating of DER formatted CRL when using admin menu. +- Added IPSEC/VPN certificate type (reduced size). +- Allow server & VPN certificates with no password. +- Allow password file location to be specified during setup. +- Allow multiple certificates with same e-mail address _OR_ common_name. +- Allow key size selection 512 to 4096 bits. +- Consolidated certificate request forms (select type from dropdown). +- CRL is automatically updated when certificates are revoked. +- Moved CRL update function from admin menu to certificate management menu. +- Changed internal extention for DER files from .crt to .der +- Changed control panel buttons to icons shamelessly stolen from phpMyAdmin & KDE. +- Changed pkcs12 download file extention to "p12". Remains "pfx" internally. +- Changed public certificate download file extention to "cer" (RFC 2585). +- Changed public certificate mime type to "application/pkix-cert" (RFC 2585). +- Changed CRL mime type to "application/pkix-crl" (RFC 2585). +- Some code clean-up and consolidation in openssl_functions.php. +- Updated help file and screenshots. +- This version has not been thoroughly tested. Please log bug report on + sourceforge site. +- Other things I can't remember. + +v0.80 +- Major restructuring to allow certificates and configuration to be + stored outside of DOCUMENT_ROOT. Some might consider this a + security enhancement. +- Eliminated most of the symbolic links between interfaces. +- Moved the admin interface from ./ca/admin to ./admin +- Removed code to fix DER certificate extensions from secure.sh + You will have to do this manually if you skipped v0.70. +- The secure.sh script will ask the location of the phpkipasswd file + and attempt to create one if necessary. +- Added support for a DEMO mode to allow switching between the + public and private interfaces using the menu. Configure it in + config.php + +v0.81 (not a public release) +- Modified VPN certificate extension to work properly with OpenVPN +- Added VPN Client Only, VPN Server Only, VPN Client & Server types +- Removed restrictions on certificate password contents and maximum length +- Fixed duplicate certificate error when requested common name was a + substring of an existing common name + +v0.82 (possibly final release) +- Fixed expiry ignored and defaults to one year when renewing certificate +- Fixed missing quotes in CA_generate_crl +- Fixed missing quotes in request_cert.php +- Added documentation regarding method=post error on php5 +- Switched on register_long_arrays in .htaccess. + Hope there is no breakage on php4. +- Added support for code signing certificates +- Trimmed some redundant code in CA_create_cert() & CA_renew_cert() +- Fixed "Go Back" button on download form +- Fixed quoting ambiguities when config.php files are created, which + causes warnings to be logged on some web server configurations. + Depending on how much this bugs you and how you upgrade, you may have + to manually fix this by correclty quoting constant definitions within + install_dir/config.php. e.g. define('CONSTANT','somevaluehere') +- Added support for multiple admins. Edit data_store/config/config.php + after installation and configuration. Idea by Micheal Braun. +- secure.sh automatically creates the 'pkiadmin' user. +- Fixed chown in secure.sh for FreeBSD compatibility. +- Fixed quote mismatch in ca/help.php +- Added support for time stamping certificates, Idea by Sebastien Bahlol. + +v0.83 (bugfix) +- Converted deprecated HTTP_SERVER_VARS to _SERVER +- Fixed emailcodesigning error in openssl_functions.php +- Fixed failure to create httpasswd file in secure.sh +- Fixed false positives when detecting if requested email certificate already exists +- Added support for 4 character TLD in email address +- Added support for short term certificates (1,3,6 months) + diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 0000000..f081754 --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,341 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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 program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..38dc8d2 --- /dev/null +++ b/Makefile @@ -0,0 +1,55 @@ +VERSION = 0.83 +UID = $(shell id -u) +GID = $(shell id -g) + +all: + @echo "Read the README file!!" + +clean: + find . -name .*.swp -follow -exec rm -f {} \; + find . -name test.php -exec rm -f {} \; + find . -name phpinfo.php -exec rm -f {} \; + find . -name "deleteme*" -exec rm -f {} \; + find . -name "newcert*.???" -exec rm -f {} \; + find . -name "privkey*.???" -exec rm -f {} \; + find . -name "newreq*.???" -exec rm -f {} \; + +distclean: clean + + find . -type d -follow -exec chmod 2777 {} \; + + rm -f ca/index.php + echo -e '' > ca/index.php + + echo ' config.php + echo 'define(PHPKI_VERSION, "$(VERSION)");' >> config.php + echo '?>' >> config.php + + rm -f index.php setup.php + ln -sf readme.php index.php + ln -sf setup.php-presetup setup.php + + find . ! -type d -follow -exec chown $(UID).$(GID) {} \; + find . ! -type d -follow -exec chmod 0666 {} \; + find . -type d -follow -exec chown $(UID).$(GID) {} \; + find . -type d -follow -exec chmod 2777 {} \; + find . -name .htaccess -follow -exec rm -f {} \; + + chmod 700 secure.sh + + echo -e 'Options FollowSymLinks' > .htaccess + echo -e 'php_flag register_globals off' >> .htaccess + echo -e 'php_flag register_long_arrays on' >> .htaccess + echo -e 'AddType application/x-x509-ca-cert .crt .pem' >> .htaccess + echo -e 'AddType application/pkix-crl .crl' >> .htaccess + echo -e 'AddType application/pkix-cert .cer .der' >> .htaccess + + @echo -e "\n\n==================================================================" + @echo -e "Point your browser to your PHPki installation to configure and" + @echo -e "create your root certificate. (i.e. http://www.domain.com/phpki/)\n" + +secure: + @./secure.sh + +fixperms: + @./secure.sh diff --git a/README b/README new file mode 100644 index 0000000..4b02b72 --- /dev/null +++ b/README @@ -0,0 +1,104 @@ +NOTICE: +This application is designed to be an easy to use "certificate factory" +requiring minimum human intervention to administer. It is intended for +use within a trusted INTRAnet for the creation and management of x.509 +e-mail digital certificates by departmental managers. IT IS NOT INTENDED +FOR USE OVER THE INTERNET. + +This application stores private keys within a sub-directory, making them +potentially susceptible to compromise. Extra care has been taken in the +design of this application to protect the security of your certificates, +on the condition that you INSTALL IT AS THE ROOT USER. However, no +software is 100% secure, AND NO PROMISES OR GUARANTEES ARE MADE! + + +REQUIREMENTS: +PHPki was developed and tested on Mandrake and RedHat GNU/Linux systems. +It requires the Apache web server, PHP, and OpenSSL. I do not as yet +know if it is sensitive to particular versions of those resources. + +Your web server must be configured with "AllowOverride All" effective +in the directory where PHPki is installed. If you don't know what this +means, then go Googling. + +With PHP 5, make sure register_long_arrays in turn on in php.ini or .htaccess. +Otherwise, you may get an error similar to "method=post was not found on this se +rver. + +INSTALLATION: +Make sure "AllowOverride All" is set in your Apache configuration file. +This is necessary because PHPki uses .htaccess files to implement HTTP +authentication and to enforce file access restrictions. If you must +change this Apache setting, don't forget to restart Apache. + +Unpack the PHPki tarball onto your web server. For example: + + cp phpki.tar.gz /var/tmp + cd /var/www/html + tar -xzvf /var/tmp/phpki.tar.gz + +To configure the certificate authority and create your root certificate, +point your browser to where you unpacked PHPki. For example: + + http://www.domain.com/phpki/ + +Enter all the requested information into the web form and click the Submit +button. If all goes well, you should see a page telling you that your +root certificate has been created. + +To access the PHPki public content menu, point your browser to your +PHPki installation (i.e. http://www.domain.com/phpki/). To access the +PHPki certificate management menu, point your browser to the "ca" +directory under your PHPki installation (i.e. https://www.domain.com/phpki/ca/). +You must use SSL (https://) to access the PHPki certificate management +menu if you have secured the application using the secure.sh script. + + +SECURITY & USERS: +From a root user shell prompt, run the "secure.sh" shell script in this +directory to set more restrictive Unix file permissions, and to create +the Apache .htaccess files which are necessary to force SSL access, HTTP +authentication, and directory access restrictions. If you don't do this +you will likely be extremely screwed! Don't say you weren't warned. + +The secure.sh script will attempt to create a file for your user list +and passwords. If it fails in that attempt, you will have to use Apache's +htpasswd utility to manually create a "phpkipasswd" file in the location +you specified during setup. + + htpasswd -cm /var/www/phpkipasswd username + +Normal users may only manage the certificates they create. Administrators +can manage all certificates. The default administrator account is +"pkiadmin". The secure.sh script will attempt to add this user to your +phpkipasswd file when it is first created. Other users can be made +administrators by carefully editing the $PHPki_admins assignment in +config/config.php under your certificate store directory. + +You may add additional users and change passwords using your browser after +you have successfully installed PHPki and created your phpkipasswd file with +at least one user. Point your browser to http://www.domain.com/phpki/admin/. + + +UPGRADING: +Install and configure as if it were a first time installation (see above). +Be sure to specify the same root certificate password and user password file +location you used with the previous version. + +From the old installation, copy all certificates, crls, and user defaults +to the store directory specified during setup. + + rm -fr store_directory/CA + cp -v --archive oldphpki/CA store_directory + cp -v --archive oldphpki/config/user-*.php newphpki/ca/config + +These upgrade instructions have not been thoroughly tested and may be +incomplete. Please be sure to fully backup your old PHPki installation before +upgrading. + + +CONTACT: +Post all correspondence to the PHPki project page +http://sourceforge.net/projects/phpki/ + +---END OF FILE--- diff --git a/TODO b/TODO new file mode 100644 index 0000000..9d0594a --- /dev/null +++ b/TODO @@ -0,0 +1,16 @@ +TO DO, IN NO PARTICULAR ORDER: + +Add CA certificate renewal to sysadmin script (ca/admin/index.php) + +Add paging features to Certificate Management Control Panel instead of +having all certificates listed on a single page. This is not really +very necessary unless one will be issuing hundreds of certificates. Even +with 200 certificates, the control panel display is very manageable. + +Use a relational database such as MySQL to maintain the certificate database +instead using the built-in OpenSSL CA feature. This will only be necessary +if it turns out that the built in OpenSSL CA doesn't perform well. + +More documentation and help files. + +Support multi-homed server certificates diff --git a/about.php b/about.php new file mode 100644 index 0000000..4e3c07f --- /dev/null +++ b/about.php @@ -0,0 +1,44 @@ + +

+PHPki is an Open Source +Web application for managing a help/glossary.html#PKI target=help/glossary> +Public Key Infrastructure within a small organizations. PHPki acts as a +mechanism for the centralized creation and management of digital certificates. +PHPki is capable of managing certificates for multiple organizations or user +accounts. + +

+PHPki requires the Apache Web Server, the PHP Scripting Language, and +OpenSSL, all of which are included with any major + Linux Operating System +distribution. + +

+This software may be freely redistributed under the terms of the +GNU Public +License provided this page and all copyright notices remain completely intact. +

+

Copyright: 2003, William E. Roadcap

+
+ +
+
+

+ + + diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 0000000..f3727e6 --- /dev/null +++ b/admin/index.php @@ -0,0 +1,127 @@ +

Contents of '.htvar($config['passwd_file']).' file:

';
+        readfile($config['passwd_file'])
+
+	?>
+	
+
method=post> + +
+ + +
method=post name=form> + + + + + +

Add User or Change Password

User ID
Password
Verify Password
+ + +
+

Missing or invalid password or password and password verification do not match.

" + + ?> +

+
method=post> + + + +
+ '; + system("htpasswd -bm $pwdfile $login $passwd 2>&1") + ?> +

+

method=post> + +
+ + +
method=post name=form> + + + +

Remove User

User ID
+ + +
+ '; + system("htpasswd -D $pwdfile $login 2>&1") + ?> +

+

method=post> + +
+ +
+
+
+ + + +
+

+ diff --git a/ca/help.php b/ca/help.php new file mode 100644 index 0000000..425b0b7 --- /dev/null +++ b/ca/help.php @@ -0,0 +1,373 @@ + +

+

+ + + + +
+ +





+ +

+

WHY PHPki

+
+PHPki is an Open Source +Web based application for managing a + "Public Key Infrastructure" +within a small organization. +PHPki may be used to create and manage +digital certificates +for use with S/MIME enabled +e-mail clients, SSL servers, and VPN applications. + +

+Most commercial +certificate authorities (CA) +require that certificates be issued to individual workstations, one at a time. +The transaction required to obtain a commercial certificate must usually take +place at the workstation on which the certifcate is to be installed, and can be +complicated, confusing, and time consuming. Such a process does not allow for +easy centralized administration of groups of certificates, where a single +person within an organization or department must request, create, and install +certificates on a number of workstations. + +

+PHPki creates standard X.509 +digital certificates which should work with most e-mail clients. +It packages private certificates in the PKCS#12 format accepted by Microsoft +e-mail clients PEM used by certain web servers. +PKCS #12 certificates usually have a .P12 +filename extension. Since most PKCS #12 certificates usually include the +certificate's private key, they should never be distributed to the general +public. PHPki's publicly distributable certificates are packaged in +standard DER format. + +

+Server + +

+ +

+

OVERVIEW

+
+The process of creating and using digital certificates with PHPki is +fairly easy. +
    +
  • +First you must download and install our +root certificate +on your computer. Everyone else you intend to exchange encrypted e-mail +with must also install our root certificate. + Everyone who installs our root certificate becomes a member of our +"circle of trust". The PHPki main menu contains an option for downloading +our root certificate. Root certificates are not private and should be widely +distributed and published on the Internet in a conspicuous location. +The more widely published a root certificate is, the more difficult it becomes +to forge. +
  • + + +

  • +You must request and download a digital certificate for each person who will +RECEIVE encrypted e-mail at your agency. Remember, having a +digital certificate does not enable one to send encrypted +e-mail, but only to receive it. Each of the certificates +you download must be installed on the respective users' workstations. +If you wish to send encrypted e-mail to someone, you must install that person's +public certificate on your computer. You can obtain another person's public +certificate simply by having them send you a +digitally signed e-mail message. When you receive the message, your e-mail +program should give you the option to add the sender's public key to your +address book or key ring. Once you have installed your digital certificates, +your users should send digitally signed messages to each person who will need +to send encrypted e-mail to them. +
  • + +

  • +Users come and go, passwords are compromised, and files are lost, such is life. +PHPki includes a certificate management system for handling these situations. +The certificate management control panel gives you the ability to +display certificates in excruciating detail, revoke a certificate when its +e-mail address is no longer valid or its public key has been compromised, +renew certificates which have or will expire, and re-download a previously +issued certificate if you've lost the original. +
  • + +

  • +There must be a method for letting outside entities know which of your +certificates have been revoked. The mechanism for doing this is the +Certificate Revocation List or CRL. A CRL is a digitally signed +list of certificates which have been revoked by a Certificate Authority. +Our CRL is updated periodically, and can be downloaded from the PHPki +Main Menu. Many e-mail clients will automatically download and install CRLs +using information embedded in certificates. However, there is no widely +adopted standard for automatic CRL checking, so it is not unusual to have +to manually install and update CRLs. +
  • + +

  • +PHPki provides a public interface for Internet users to download our root +certificate and certificate revokation list. A certificate search feature +is also provided to allow easy distribution of public certificates over the +Internet. +
  • +
+
+ +

+

THE MAIN MENU

+

+

+
+

+All of the PHPki primary functions can be accessed from the Main Menu. +It is possible to navigate back to the Main Menu from any screen by clicking the +"Menu" link in the upper right corner of each page. Clicking the Public link will open a new browser window to the public content menu where +the general public may search for certificates and download the +Root Certificate and Certificate Revocation List. +

+ +

+

REQUESTING A NEW CERTIFICATE

+
+When you select "Request a New Certificate" from the Main Menu, you will be +presented with the Certificate Request Form.
+

+

+

+This form is used to collect the minimum necessary information required to +issued a new digital certificate. All fields must be completed. +

    +
  • +E-mail User's Full Name: Enter the full name of the user for which the certificate will be issued. +
  • +

  • +E-mail Address: Enter the e-mail address of the user for which the certificate is to be issued. This field will be checked for proper e-mail address +format, but the e-mail address is not verified otherwise. +
  • +

  • +Organization: Enter the full name of your organization (i.e. ACME Shoe Repair). +
  • +

  • +Department/Unit: Enter the name of the department or unit in which the +user works. (i.e. Accounting Department). +
  • +

  • +Locality: Enter the name of the City or County in which the organization +is located. +
  • +

  • +State/Province: Enter the name of the State or Province in which the organization +is located. +
  • +

  • +Country: Enter the name of the Country in which the organization +is located. +
  • +

  • +Certificate Password: Enter a password to protect the certificate. +If you enter a password, it must ben enter twice for verification. +This password will be used to encrypt the private key which will be packaged +with the completed certificate. It may also be required when installing a PKCS#12 +certificate. This password should be handled with the +utmost security and should never be lost, as it cannot be recovered under +any circumstance. If this password is lost, you must immediately +revoke the certificate and request/create a new certificate for the user. +
  • +

  • +Certificate Life: Select the number of years you want the certificate to +be valid. Although it is common practice to issue certificates which are valid +for only one year, the option to issue certificates for a longer period is +available should you wish to be rebel. The certificate may be revoked or +renewed at any point during its life. +
  • +

  • +Key Size: Select this size of your private key in bits. Larger +keys are considered more secure. However, certain VPN applications may +have difficulty with keys larger than 1024 bits. +
  • +

  • +Certificate Use: Select the purpose for which the certificate will +be use. E-mail certifcates have different attributes from SSL server +certifcates and may not be interchangeable. Some IPSEC/VPN applications +may be sensitive to large certificates, so those certificates contain less +embedded information to keep them small. +
  • +
+ +

+When you have complete filling in the form, click the "Submit Request" button. +The information you submitted will be checked for errors, and a confirmation +screen will be displayed. +

+

+

+Clicking the "Yes! Create and Download" button will cause a file download +window to open in your browser, allowing you to save the certificate on your +computer under whatever name you choose. The default name for each certificate +is derived from the e-mail address provided in the certificate request form. +You may download the certificate as many time as you wish as long as your +browser remains on this page. If you navigate from this page, you will have +to use the Certificate Management Control Panel to download the certificate +again. Be sure to save all of your certificates in a safe and secure +place. Doing so will make it easier for you to re-install a certificate on a +user's workstation should the need arise.
+

+After the download window closes, you may click the "Back" button to return +to the form and request another certificate. All of the data you previously +entered will be retained. This is to allow you to issue a large number of +certificates without having to re-enter much of the form. As well, your +form input will be saved as your default values for the future sessions
+

+ + +

+

MANAGING YOUR CERTIFICATES WITH THE CONTROL PANEL

+
+PHPki provides one convenient place to manage your certificates. +It is called the Certificate Management Control Panel. +

+

+

+With the Control Panel you can display, download, revoke, and +renew your certificates by simply clicking on the appropriate button to the +right of each certificate entry. Your certificates are listed in columnar +format, with the left-most color coded "Status" column showing whether a +certificate is "Valid" or +"Revoked". The listing can be sorted in any order +by clicking on the column headings. An arrow graphic +   beside a column heading +indicates which column is being used to sort the listing. Clicking on the +arrow graphic will cause the listing to alternate between ascending and +descending sort order. You may find these sort features particularly useful if +you are careful to plan and utilize the Department/Unit and +Locality fields to categorize your certificates according to +your particular organizational needs. +

+

REVOKING A CERTIFICATE

+
+At times it may become necessary to revoke or invalidate a certificate. This +usually happens when an e-mail address is no longer valid, or the certificate's +private key has been lost or compromised. +

+To revoke a certificate, click on the   icon next to the certificate entry in the Control Panel. +

+

+

+You will then be asked to confirm or cancel the revocation. Be absolutely +sure of what you wish to do before clicking the "Yes" button. Once a +certificate is revoked, it cannot be un-revoked. Well, this isn't completely +true, as a revoked certificate can be renewed. Renewing a revoked certificate +results in a new certificate being issued. Certificate +renewal is covererd later. +

+

+

+If you click the "Yes" button, the certificate is revoked with no further +interaction. The certificate's status in the Control Panel +will change to Revoked. +

+ +

+

DISPLAYING CERTIFICATE DETAILS

+
+Certificates may be displayed in full detail by clicking the +  icon next to a certificate's +entry in the Control Panel. Although some users may find this +feature useful, many will not find anything of interest in it. +

+

+
+ +

+

RENEWING A CERTIFICATE

+
+Certificates expire periodically. The usually length a time for which a +certificate is valid is one year. With PHPki, you have the option to +issue certificates with a more extended life span. Regardless, sooner or later +your certificates will begin to expire. +

To renew a certificate which has expired or is near expiration, simply click +the   icon next to the +certifcate's Control Panel entry. You will then be presented +with a certificate renewal form. +

+

+

+The certificate renewal form takes the values for Common Name, +E-mail Address, Organization, etc. from the original certificate. +Those fields are disabled in the form, and cannot be changed. +You are required to enter the original certificate's password and select +a life span for the new certificate. If you do not enter the correct +password that was assigned to the original certificate when it was created, +you will not be able to renew the certificate. You may cancel this operation +by clicking the "Back" button, which will take you back to the +Control Panel. +

+

+

+If you click the "Submit Request" button to renew the certificate, it is +renewed with no further interaction, and you will be returned to the +Control Panel. You will notice a new +Valid certificate in the Control Panel, +and the old expired certificate is marked Revoked. +

+ +

+

DOWNLOADING A CERTIFICATE

+
+If you lose the original file you downloaded when you first created a +certificate, you may download another copy of a certificate at any time by +clicking the +  icon next to the certificate's entry +in the Control Panel. When downloading a certificate, you will +be reminded that the certificate is a +PRIVATE certificate, which +SHOULD NEVER BE DISTRIBUTED TO THE PUBLIC. +You may choose to download PKCS #12 or PEM formatted bundles. +

+

+
+ +

+

GLOSSARY

+
+Click here to view the complete +PHPki glossary of terms. +
+ + +

+

GETTING ADDITIONAL HELP

+
+ +
+
+ + diff --git a/ca/index.php b/ca/index.php new file mode 100644 index 0000000..9a6d04d --- /dev/null +++ b/ca/index.php @@ -0,0 +1,3 @@ +-e diff --git a/ca/main.php b/ca/main.php new file mode 100644 index 0000000..ab634c5 --- /dev/null +++ b/ca/main.php @@ -0,0 +1,97 @@ + +

Certificate Revocation List Updated

+

+

method=post> + +
+ '.CA_crl_text().''; + } + else { + ?> + +

There was an error updating the Certificate Revocation List.


+
+

Debug Info:

+
+
+
method=post> +

+ +

+

+ +
+
+
+ + + + + + + + + + + + + + + + + + +
+

+ diff --git a/ca/manage_certs.php b/ca/manage_certs.php new file mode 100644 index 0000000..7ce07f6 --- /dev/null +++ b/ca/manage_certs.php @@ -0,0 +1,411 @@ +

YOU ARE A VERY BAD BOY!

+

Certificate Details

+

(#)
')?>

+

REVOKED '.$revoke_date.'

'; + + print '
'.CA_cert_text($serial).'
'; + break; + +case 'dl-confirm': + printHeader('ca'); + + $rec = CAdb_get_entry($serial); + + ?> +

You are about to download the PRIVATE certificate key for

+

DO NOT DISTRIBUTE THIS FILE TO THE PUBLIC!

+
+ File type: + + + +   or   + +
+ +

You are about to REVOKE the following certificate: + + + + '.htvar($rec[serial]).'
+ '.htvar($rec[common_name]).'
+ '.htvar($rec[email]).'
+ '.htvar($rec[organization]).'
+ '.htvar($rec[unit]).'
+ '.htvar($rec[locality]).'
+ '.htvar($rec[province]).'
+ '.htvar($rec[country]).'
+ +
+

+ Serial Number
+ User's Name
+ Email Address
+ Organization
+ Department/Unit
+ Locality
+ State/Province
+ Country
+

+

Are you sure?

+

+ + +   + +
'; + + break; + +case 'revoke': + $ret = true; + if ($submit == 'Yes') + list($ret, $errtxt) = CA_revoke_cert($serial); + + if (! $ret) { + printHeader('ca'); + + print "
"; + ?> + +

There was an error revoking your certificate +.


+
+

Debug Info:

+
+
+

+ +

+

+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Certificate Renewal Form

Common Name
E-mail Address
Organization
Department/Unit
Locality
State/Province
Country
Certificate Password
Certificate Life
+
  +
+
+ + > +
+
+ "; + ?> + +

There was an error creating your certificate +.


+
+

Debug Info:

+
+
+

+ +

+ + + + + + + + '; + $headings = array( + status=>"Status", issued=>"Issued", expires=>"Expires", + common_name=>"User's Name", email=>"E-mail", + organization=>"Organization", unit=>"Department", + locality=>"Locality" + ); + + foreach($headings as $field=>$head) { + print ''; + } + print ''; + + $x = "^[$show_valid$show_revoked$show_expired]"; + + if (in_array($PHPki_user, $PHPki_admins)) { + $x = "$x.*$search"; + } + else { + $x = "$x.*$search.*$PHPki_user|$x.*$PHPki_user.*$search"; + } + + $db = csort(CAdb_to_array($x), $sortfield, ($ascdec=='A'?SORT_ASC:SORT_DESC)); + + $stcolor = array(Valid=>'green',Revoked=>'red',Expired=>'orange'); + + foreach($db as $rec) { + print ' + + + + + + + + + '; + + } + + print '
CERTIFICATE MANAGEMENT CONTROL PANEL
+
" method=get name=filter> + Search: +       >Valid +   >Revoked +   >Expired +       +
+
'.$head.''; + + if ($sortfield == $field) { + print ' '. + '\'Change'; + } + + print '
' .$rec[status].''.$rec[issued].''.$rec[expires].''.$rec[common_name].'' . htvar($rec['email']) . ''.htvar($rec[organization]).''.htvar($rec[unit]).''.htvar($rec[locality]).''. + 'Display'; + + if ($rec['status'] == 'Valid') { + print ' + '. + 'Download + '. + 'Revoke'; + } + print ' + '. + 'Renew
'; + + printFooter(); +} +?> diff --git a/ca/policy.html b/ca/policy.html new file mode 100644 index 0000000..6f6ef88 --- /dev/null +++ b/ca/policy.html @@ -0,0 +1,78 @@ + + + +Certificate Authority Agreement + + + + +

Certificate Authority Agreement

+

Policy and Practices

+ +

+

This is a statement of practices by this Digital Certificate Authority. +Your use of this Certificate Authority constitutes your and/or your agency's +understanding and full acceptance of these practices and all associated risks. +Please have an authorized person at your agency sign this document and fax it to 000-000-0000 + +

This document may not be all encompassing, and we reserve the right to modify it at any time. + +

    +
  • The sole role of this Certificate Authority is +to provide and maintain a password protected software application for the easy +and instant creation and management of standard x.509 personal digital +certificates for e-mail encryption. We assume no responsibility for +verifying the identity of any persons other than that of the limited number of +authorized users of the software. +We accept no liability for damages resulting from the use, misuse, +or compromise of the software application or its host server. + +

  • As an authorized user of the software, you are in effect THE Certificate Authority for your +agency. As such, you are solely +responsible for authenticating the identity of the persons for whom you obtain +certificates. We accept no +responsibility or liability for non-repudiation in any digital certificate +created by this software. You agree that +password protection to the application by authorized certificate managers, +and personal identity management by +those managers is sufficient to create a chain of trust for non-repudiation +in all digital certificates created using the software. + +

  • No more than two(2) +users at your agency should have access to your agency's Certificate Authority +password. We should be notified +immediately, via e-mail, when the employment of any +authorized user at your agency is terminated so that a new password can be +issued. + +

  • This Certificate +Authority software application is accessed via the Internet using standard SSL +or Secure Server encryption mechanisms. +Although steps have been taken to protect the security and availability +of the host server and application, its exposure to the Internet as well as any +presently unknown security flaws could lead to potential compromise of the +software and your certificates. + +

  • No promise is made as +to the availability of the software in the event of hardware, software, or +telecommunications failure or maintenance.  +No advanced notice will be given when the software must be temporarily +taken off line for service. + +

  • In order to provide +software which can easily create "instant" certificates it is +necessary to store all private keys on the host server. As such, all private keys are potentially exposed +to the Internet and suffer some risk of unauthorized access. However, since all private keys ARE +ENCRYPTED using a password provided by you, they are unlikely to be usable by +any intruder. + +

  • A publicly accessible +web page is provided for interested Internet users to download the Certificate +Authority root certificate, certificate revocation list, and search for the +e-mail addresses and public certificates of users. So as to avoid e-mail address scraping by spammers, no static +content with users' e-mail addresses is available. + +
+ + + diff --git a/ca/request_cert.php b/ca/request_cert.php new file mode 100644 index 0000000..9b03045 --- /dev/null +++ b/ca/request_cert.php @@ -0,0 +1,330 @@ + + + + + + + + + + + + +'; + + +switch ($form_stage) { + +case 'validate': + $er = ''; + + if (! $country) $er .= 'Missing Country
'; + if (! $province) $er .= 'Missing State/Province
'; + if (! $locality) $er .= 'Missing Locality (City/County)
'; + if (! $organization) $er .= 'Missing Organization (Company/Agency)
'; + if (! $unit) $er .= 'Missing Unit/Department
'; + if (! $common_name) $er .= 'Missing E-mail User\'s Full Name
'; + if (! $email) $er .= 'Missing E-mail Address
'; + + if (($cert_type == 'email' || $cert_type == 'email_signing') && ! $passwd) $er .= 'Missing Certificate Password
'; + if (($cert_type == 'email' || $cert_type == 'email_signing') && ! $passwdv) $er .= 'Missing Certificate Password Verification "Again"
'; + + if ( $passwd && strlen($passwd) < 8 ) + $er .= 'Certificate password is too short.
'; + + if ( $passwd and $passwd != $passwdv ) + $er .= 'Password and password verification do not match.
'; + + //if ( ! is_alnum($passwd) or ! is_alnum($passwdv) ) + // $er .= 'Password contains invalid characters.
'; + + if ( $email && ! is_email($email) ) + $er .= 'E-mail address ('. htvar($email) . ') may be invalid.
'; + + if ( $er ) + $er = '

ERROR(S) IN FORM:

' . $er . '

'; + + + if ($email && ($serial = CAdb_in($email,$common_name))) { + $er = ''; + $certtext = CA_cert_text($serial); + $er .= '

A valid certificate already exists for ' . htvar("$common_name <$email>") . '

'; + $er .= '
 ' . htvar($certtext) . ' 
'; + + } + + if ($er) { + printHeader(); + ?> + +
+ + +
+ + "; + + printFooter(); + break; + } + +case 'confirm': + printHeader(); + + ?> +

You are about to create a certificate using the following information:

+ + + + + +
+

+ User's Name
+ E-mail Address
+ Organization
+ Department/Unit
+ Locality
+ State/Province
+ Country
+ Certificate Life
+ Key Size
+ Certificate Use
+

+ '; + print htvar($email) . '
'; + print htvar($organization) . '
'; + print htvar($unit) . '
'; + print htvar($locality) . '
'; + print htvar($province) . '
'; + print htvar($country) . '
'; + print htvar($expiry). ' Year'.($expiry == 1 ? '' : 's').'
'; + print htvar($keysize). ' bits
'; + print htvar($cert_type). '
'; + ?> +
+ +

Are you sure?

+

+ + +   + +

+ + '; + fwrite($fp,$x); + fclose($fp); + + break; + +case 'final': + if ($submit == "Yes! Create and Download") { + if (! $serial = CAdb_in($email,$common_name)) { + list($ret,$errtxt) = CA_create_cert($cert_type,$country, $province, $locality, $organization, $unit, $common_name, $email, $expiry, $passwd, $keysize); + + if (! $ret) { + printHeader(); + + ?> +
method=post> + +

There was an error creating your certificate.


+
+

Debug Info:

+
+
+

+ + +

+

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Certificate Request Form

Common Name
(i.e. User real name or computer hostname)
E-mail Address
Organization (Company/Agency)
Department/Unit
Locality (City/County)
State/Province
Country
Certificate Password    Again
Certificate Life
Key Size
Certificate Use:
* All fields are required
+
+ diff --git a/config.php b/config.php new file mode 100644 index 0000000..188ac19 --- /dev/null +++ b/config.php @@ -0,0 +1,3 @@ + diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..52bef95 --- /dev/null +++ b/css/style.css @@ -0,0 +1,172 @@ +h1 { + font-size: 32px; +} + +h2 { + font-size: 24px; +} + +h3 { + font-size: 18px; +} + +body { + margin: 10px; + padding: 0; + background: #fafaff; + font-family: Arial, Veranda, Helvetica, sans-serif; + font-size: 12px; +} + +img { + border: 0; +} + +a { + color: #00F; + background-color: transparent; +} + +a:link, a:active, a:visited { + color: #00F; + background-color: transparent; +} + +a.headermenu:link, a.headermenu:active, a.headermenu:visited { + text-decoration: underline; + color: #00F; + background-color: transparent; + padding-left: 8px; +} + +form { + padding: 0; + margin: 0; +} + + +fieldset { + border: 2px solid black; + margin-left: 10px; + padding: 10px; + width: 700px; + font-size: 10px; +} + +legend { + background-color: rgb(200, 220, 240); + border: 2px solid black; + padding: 0.25em; + padding-top: 0.1em; + font-size: 12px; +} + +table { + font-size: 12px; + margin-right: .1in; +} + +th { + font-weight: bold; + background-color: #AFC3E4; + padding: 3px; + color: #323C4D; + text-align: center; + vertical-align: middle; + border: 1px solid #606060; + white-space: nowrap; +} + +td { + background-color: #DEE3EC; + padding: 3px; + text-align: left; + vertical-align: middle; + border: 1px solid #a0a0a0; +} + +.menu { + height: 22px; + font-size: 13px; + text-align: center; + vertical-align: bottom; + border: 1px solid #808080; + border-left: 2px solid #808080; + border-bottom: 2px solid #808080; + color: #000000; +} + +.menu-pad { + height: 22px; + font-size: 13px; + text-align: center; + padding-left: 1em; + padding-right: 1em; + vertical-align: bottom; + border: 1px solid #808080; + border-left: 2px solid #808080; + border-bottom: 2px solid #808080; + color: #000000; +} +.menu a { + vertical-align: bottom; + text-decoration: none; + font-size: 13px; + +} + +.headermenu-ie { + text-align: right; + margin-right: 0.1in; + margin-top: -0.20in; +} + +.headermenu-konq { + text-align: right; + margin-right: 0.1in; + margin-top: -0.25in; +} + + +.logo-ie { + font-family: 'impact', sans-serif; + font-size: 60pt; + font-weight: bold; + color: #99caff; + margin-top: -0.20in; + margin-bottom: 0; + margin-right: 0.2in; + text-align: left; +} + +.title-ie { + font-family: 'impact', sans-serif; + font-size: 22pt; + font-weight: bold; + font-style: italic; + margin-right: 0.4in; + margin-top: -0.52in; + margin-bottom: 0; + text-align: left; } + +.logo-konq { + font-family: 'impact', sans-serif; + font-size: 62pt; + font-weight: bold; + color: #99caff; + margin-top: -0.20in; + margin-bottom: 0; + margin-right: 0.2in; + text-align: left; +} + +.title-konq { + font-family: 'impact', 'sans-serif'; + font-size: 24pt; + font-weight: bold; + font-style: italic; + margin-right: 0.4in; + margin-top: -0.55in; + margin-bottom: 0; + text-align: left; +} diff --git a/help.php b/help.php new file mode 100644 index 0000000..f9b1ac3 --- /dev/null +++ b/help.php @@ -0,0 +1,16 @@ + +

PHPki HELP FILES

+help/PKI_basics.html>

PKI and E-mail Encryption - A Brief Explanation

+help/cacert_install_ie.html>

Installing Our Root Certificate For Use With Outlook and Outlook Express

+

help/usercert_install_ie.html>

Installing Your Personal E-mail Certificate For Use With Outlook and Outlook Express

+

help/glossary.html>

Glossary

+
+ diff --git a/help/PKI_basics.html b/help/PKI_basics.html new file mode 100644 index 0000000..615fa10 --- /dev/null +++ b/help/PKI_basics.html @@ -0,0 +1,64 @@ + + + +PKI and E-mail Encryption - A Brief Explanation + + +

PKI and E-mail Encryption - A Brief Explanation

+ +PKI stands for Public Key Infrastructure. PKI is Information +Technology infrastructure that enables users of a basically unsecure public +network (such as the Internet) to securely and privately exchange data through +the use of a public and a private +cryptographic key pair that is obtained and shared through a +trusted Authority. + +

+Public and private keys are like two halves of a single key. PKI encryption +algorithms are designed such that a public key is used to encrypt or +"lock" a message, and only the complementary private key can "unlock" that +message. +Think of a bank vault or safe that can only be unlocked by two individuals +using two different but complementary keys. Neither of those keys can be used +by itself to unlock the vault. + +

+In practice, individuals wishing to exchange encrypted e-mail +will agree to mutually trust one or more +Certificate Authorities(CA) by downloading and installing each trusted Authority's +root certificate on their computers. +They will each obtain their own personal +digital certificate +from a trusted Certificate Authority, and install them on their +respective computers. +Because they mutually trust the Certificate Authorities, they trust each other's +digital certificates. More specifically, they trust the +public keys contained within +their personal digital certificates which have been +digitally signed by a +trusted Certificate Authority. +They will then exchange their trusted public keys by sending each other +digitally signed e-mail messages. Once each party has the other's public key, +they may exchange trusted and encrypted messsages. + +

+Public key exchange and encryption is like exchanging notarized documents. +One trusts a notarized document because a trusted third party, the Notary +Public, has signed it. The Certificate Authority is the Notary Public, and +the public keys are the documents. + +

+Remember, having a personal digital certificate alone does not +give one the ability to send encrypted e-mail to others, but only allows the +receipt of encrypted e-mail. PKI is a cooperative encryption +standard. Both parties who are exchanging encrypted messages must have +personal digital certificates, they must trust the Certificate Authority +which issued the other persons certificate, and they must exchange +public keys with each other, as described above. + +

+The process of installing certificates and exchanging public keys is dependent +upon the e-mail application one uses, and is beyond the scope of this document. + + + diff --git a/help/cacert_install_ie.html b/help/cacert_install_ie.html new file mode 100644 index 0000000..bf62331 --- /dev/null +++ b/help/cacert_install_ie.html @@ -0,0 +1,29 @@ + + +Root Certificate Installation for Outlook & Outlook Express + + + +

Root Certificate Installation for Outlook & Outlook Express

+

A Step-by-Step Guide


+

+

+

Open the folder which holds the certificates you have downloaded.
+Right-click on the certificate you wish to install, and select +Install Certificate from the context menu. +


+

Click the Next button in the Certificate Wizard +welcome window. +


+

Click the Next button in the Select a Certificate Store window. +


+

Click the Finish button in the Complete the Certificate.. window. +


+

You may be asked to confirm the root certificate installation. Click the Yes button if a window like this appears. +


+

Windows confirms the root certificate was successfully imported.
+You may now install your personal e-mail certificate. + +

+ + diff --git a/help/glossary.html b/help/glossary.html new file mode 100644 index 0000000..28c2044 --- /dev/null +++ b/help/glossary.html @@ -0,0 +1,144 @@ + + +PHPki Glossary + + + + + +

+ + + +

PUBLIC KEY INFRASTRUCTURE

+PKI stands for Public Key Infrastructure. PKI is IT infrastructure that enables users of a basically unsecure public network (such as the Internet) to securely and privately exchange data through the use of a public and a private cryptographic key pair that is obtained and shared through a trusted authority. + +PKI is not only software or hardware. It is an infrastructure. So, PKI is a combination of products, services, facilities, policies, procedures, agreements, and people. All of these elements work together to provide for secure interactions on the Internet and other open networks. PKI is not a single monolithic entity, but a distributed system. The component elements may include multiple organization-specific public key infrastructures that are interoperable and interconnected. +
+ +

+ + + +

DIGITAL CERTIFICATE

+

+An attachment to an electronic message used for security purposes. The most common use of a digital certificate is to verify that a user sending a message is who he or she claims to be, and to provide the receiver with the means to encode a reply. + +

An individual wishing to send an encrypted message applies for a digital certificate from a Certificate Authority (CA). The CA issues an encrypted digital certificate containing the applicant's public key and a variety of other identification information. The CA makes its own public key readily available through print publicity or perhaps on the Internet. + +

The recipient of an encrypted message uses the CA's public key to decode the digital certificate attached to the message, verifies it as issued by the CA and then obtains the sender's public key and identification information held within the certificate. With this information, the recipient can send an encrypted reply. + +

The most widely used standard for digital certificates is X.509. +

+ +

+ + + +

CERTIFICATE AUTHORITY

+A trusted third-party organization or company that issues digital certificates used to create digital signatures and public-private key pairs. The role of the CA in this process is to guarantee that the individual granted the unique certificate is, in fact, who he or she claims to be. Usually, this means that the CA has an arrangement with a financial institution, such as a credit card company, which provides it with information to confirm an individual's claimed identity. CAs are a critical component in data security and electronic commerce because they guarantee that the two parties exchanging information are really who they claim to be. +
+ +

+ + + +

PUBLIC KEY ENCRYPTION

+A cryptographic system that uses two keys -- a public key known to everyone and a private or secret key known only to the recipient of the message. When John wants to send a secure message to Jane, he uses Jane's public key to encrypt the message. Jane then uses her private key to decrypt it. + +

An important element to the public key system is that the public and private keys are related in such a way that only the public key can be used to encrypt messages and only the corresponding private key can be used to decrypt them. Moreover, it is virtually impossible to deduce the private key if you know the public key. +

+ +

+ + + +

S/MIME

+S/MIME (Secure Multi-Purpose Internet Mail Extensions) is a secure method of sending e-mail that uses the RSA encryption system. S/MIME is included in the latest versions of the Web browsers from Microsoft and Netscape and has also been endorsed by other vendors that make messaging products. RSA has proposed S/MIME as a standard to the Internet Engineering Task Force (IETF). +
+ +

+ + + +

RSA

+RSA is an Internet encryption and authentication system that uses an algorithm developed in 1977 by Ron Rivest, Adi Shamir, and Leonard Adleman. The RSA algorithm is the most commonly used encryption and authentication algorithm and is included as part of the Web browsers from Microsoft and Netscape. It's also part of Lotus Notes, Intuit's Quicken, and many other products. The encryption system was owned by RSA Security, but a recent patent expiration placed it into the public domain. The technologies are part of existing or proposed Web, Internet, and computing standards. +
+ +

+ + + +

ROOT CERTIFICATE

+A root certificate is like a MASTER +digital certificate. +You must install a certificate authority's root certificate +before you can trust other certificates issued by that same certificate +authority. Root certificates are used to "sign" other certificates. +A signature by a root certificate is somewhat analogous to "notarizing" a +document in the physical world. When you install a root certificate on your +computer, you are saying you "trust" that certification authority and all +certificates it signs. +
+ +

+ + + +

DIGITAL SIGNATURE

+A digital code that can be attached to an electronically transmitted message +that uniquely identifies the sender. Like a written signature, the purpose of +a digital signature is to guarantee that the individual sending the message +really is who he or she claims to be. Digital certificates inherently provide +digital signature capability to most S/MIME enable e-mail clients. Digitally +signing an e-mail usually provides the recipient the with the sender's public +key, so the recipient may then send encrypted e-mail back to the sender. +
+ +

+ + + +

X.509

+The most widely used standard for defining digital certificates. X.509 is +actually an ITU Recommendation, which means that has not yet been officially +defined or approved. As a result, companies have implemented the standard in +different ways. For example, both Netscape and Microsoft use X.509 certificates +to implement SSL in their web servers and browsers. But an X.509 certificate +generated by Netscape may not be readable by Microsoft products, and vice +versa. +
+ +

+ + + +

PEM

+PEM is a widely used standard for storing digital certificates. +A PEM encoded file can contain all of private keys, public keys, and +(x.509) certificates. It is the default format for OpenSSL. +It stores data in Base64 encoded format, surrounded by ascii headers, so it is +suitable for text mode transfers between systems. PEM files usually end with +a .PEM extension. +
+ +

+ + + +

DER

+DER is a widely used standard for storing digital certificates. A DER encoded +file can contain all of private keys, public keys, and (x.509) +certificates. DER is a binary encoded headerless format. DER files usually +end with a .CRT or .CER extension. +
+ +

+ + + +

PKCS #12

+PKCS #12 (a.k.a. Personal Information Exchange Standard) is a standard for storing private keys and certificates securely (well sort of). It is used in (among other things) Netscape and Microsoft Internet Explorer with their import and export options. PKCS12 files usually end with a .PFX extension. +
+ +

diff --git a/help/usercert_install_ie.html b/help/usercert_install_ie.html new file mode 100644 index 0000000..c223c34 --- /dev/null +++ b/help/usercert_install_ie.html @@ -0,0 +1,40 @@ + + +Personal E-mail Certificate Installation for Outlook & Outlook Express + + + +

Personal E-mail Certificate Installation for Outlook & Outlook Express

+

A Step-by-Step Guide


+

+

+

Open the folder which holds the certificates you have downloaded.
+Right-click on the certificate you wish to install, and select +Install PFX from the context menu. +


+

Click the Next button in the Certificate Wizard +welcome window. +


+

Click the Next button in the Select File to Import window. +


+

The personal e-mail certificate files created by PHPki contain an encrypted +copy of your private key. When your certficate was created, a password was +given to PHPki to encrypt the private key. The same password is used to +decrypt your private key and install the certificate. Do not forget or lose +this password as it cannot be recovered under any circumstance. +Select the Enable strong private key protection option if you +would like Windows to add an additional layer of password protection to use +your certificate. This is not necessary, and will not be covered further here. +There is no need to select the Mark the private key as exportable +option. Enter your certificate password and click the Next button +in the Password Protection for Private Keys window. +


+

Click the Next button in the Select a Certificate Store window. +


+

Click the Finish button in the Complete the Certificate.. window. +


+

Windows confirms the root certificate was successfully imported.
+ +

+ + diff --git a/images/bt0009.gif b/images/bt0009.gif new file mode 100644 index 0000000..7f24fdf Binary files /dev/null and b/images/bt0009.gif differ diff --git a/images/cert-request-form.png b/images/cert-request-form.png new file mode 100644 index 0000000..4941380 Binary files /dev/null and b/images/cert-request-form.png differ diff --git a/images/cert-wizard1-welcome.jpg b/images/cert-wizard1-welcome.jpg new file mode 100644 index 0000000..3e493f7 Binary files /dev/null and b/images/cert-wizard1-welcome.jpg differ diff --git a/images/cert-wizard2-select-file.jpg b/images/cert-wizard2-select-file.jpg new file mode 100644 index 0000000..8b307ba Binary files /dev/null and b/images/cert-wizard2-select-file.jpg differ diff --git a/images/cert-wizard3-password.jpg b/images/cert-wizard3-password.jpg new file mode 100644 index 0000000..24d3f3f Binary files /dev/null and b/images/cert-wizard3-password.jpg differ diff --git a/images/cert-wizard4-select-store.jpg b/images/cert-wizard4-select-store.jpg new file mode 100644 index 0000000..1d29314 Binary files /dev/null and b/images/cert-wizard4-select-store.jpg differ diff --git a/images/cert-wizard5-root-final.jpg b/images/cert-wizard5-root-final.jpg new file mode 100644 index 0000000..974c783 Binary files /dev/null and b/images/cert-wizard5-root-final.jpg differ diff --git a/images/cert-wizard5-user-final.jpg b/images/cert-wizard5-user-final.jpg new file mode 100644 index 0000000..5ee463a Binary files /dev/null and b/images/cert-wizard5-user-final.jpg differ diff --git a/images/confirm-delete-cacert.jpg b/images/confirm-delete-cacert.jpg new file mode 100644 index 0000000..ee438fc Binary files /dev/null and b/images/confirm-delete-cacert.jpg differ diff --git a/images/confirm-download.png b/images/confirm-download.png new file mode 100644 index 0000000..dcccbea Binary files /dev/null and b/images/confirm-download.png differ diff --git a/images/confirm-install-cacert.jpg b/images/confirm-install-cacert.jpg new file mode 100644 index 0000000..57eda62 Binary files /dev/null and b/images/confirm-install-cacert.jpg differ diff --git a/images/control-panel.jpg b/images/control-panel.jpg new file mode 100644 index 0000000..b401751 Binary files /dev/null and b/images/control-panel.jpg differ diff --git a/images/ctrl-panel-after-renew.png b/images/ctrl-panel-after-renew.png new file mode 100644 index 0000000..cf77c8c Binary files /dev/null and b/images/ctrl-panel-after-renew.png differ diff --git a/images/ctrl-panel-after-revoke.png b/images/ctrl-panel-after-revoke.png new file mode 100644 index 0000000..dca188a Binary files /dev/null and b/images/ctrl-panel-after-revoke.png differ diff --git a/images/ctrl-panel-before.png b/images/ctrl-panel-before.png new file mode 100644 index 0000000..a02102c Binary files /dev/null and b/images/ctrl-panel-before.png differ diff --git a/images/display-revoked.png b/images/display-revoked.png new file mode 100644 index 0000000..54d380d Binary files /dev/null and b/images/display-revoked.png differ diff --git a/images/display.png b/images/display.png new file mode 100644 index 0000000..24e1ec6 Binary files /dev/null and b/images/display.png differ diff --git a/images/down.png b/images/down.png new file mode 100644 index 0000000..f545e03 Binary files /dev/null and b/images/down.png differ diff --git a/images/downarrow-blue.gif b/images/downarrow-blue.gif new file mode 100644 index 0000000..0cc9922 Binary files /dev/null and b/images/downarrow-blue.gif differ diff --git a/images/download-confirm.png b/images/download-confirm.png new file mode 100644 index 0000000..f1e1d5d Binary files /dev/null and b/images/download-confirm.png differ diff --git a/images/download.png b/images/download.png new file mode 100644 index 0000000..cafac61 Binary files /dev/null and b/images/download.png differ diff --git a/images/downloaded-certs.jpg b/images/downloaded-certs.jpg new file mode 100644 index 0000000..1bc7eca Binary files /dev/null and b/images/downloaded-certs.jpg differ diff --git a/images/edit.png b/images/edit.png new file mode 100644 index 0000000..05711a0 Binary files /dev/null and b/images/edit.png differ diff --git a/images/grey-bullet.gif b/images/grey-bullet.gif new file mode 100644 index 0000000..282f071 Binary files /dev/null and b/images/grey-bullet.gif differ diff --git a/images/import-successful.jpg b/images/import-successful.jpg new file mode 100644 index 0000000..035c115 Binary files /dev/null and b/images/import-successful.jpg differ diff --git a/images/main-menu.png b/images/main-menu.png new file mode 100644 index 0000000..b6ac1c5 Binary files /dev/null and b/images/main-menu.png differ diff --git a/images/public-menu.png b/images/public-menu.png new file mode 100644 index 0000000..fe4b24d Binary files /dev/null and b/images/public-menu.png differ diff --git a/images/public_menu.png b/images/public_menu.png new file mode 100644 index 0000000..cf25e6d Binary files /dev/null and b/images/public_menu.png differ diff --git a/images/renew.png b/images/renew.png new file mode 100644 index 0000000..6b27550 Binary files /dev/null and b/images/renew.png differ diff --git a/images/renewal-form.png b/images/renewal-form.png new file mode 100644 index 0000000..fc79557 Binary files /dev/null and b/images/renewal-form.png differ diff --git a/images/request-confirm-form.png b/images/request-confirm-form.png new file mode 100644 index 0000000..111fdab Binary files /dev/null and b/images/request-confirm-form.png differ diff --git a/images/request-form.png b/images/request-form.png new file mode 100644 index 0000000..3ca066e Binary files /dev/null and b/images/request-form.png differ diff --git a/images/revoke-confirm.png b/images/revoke-confirm.png new file mode 100644 index 0000000..f0221f9 Binary files /dev/null and b/images/revoke-confirm.png differ diff --git a/images/revoke.png b/images/revoke.png new file mode 100644 index 0000000..6fc4d3b Binary files /dev/null and b/images/revoke.png differ diff --git a/images/right-click-install-cacert.jpg b/images/right-click-install-cacert.jpg new file mode 100644 index 0000000..e88a015 Binary files /dev/null and b/images/right-click-install-cacert.jpg differ diff --git a/images/right-click-install-usercert.jpg b/images/right-click-install-usercert.jpg new file mode 100644 index 0000000..c1b8b7c Binary files /dev/null and b/images/right-click-install-usercert.jpg differ diff --git a/images/search-form.png b/images/search-form.png new file mode 100644 index 0000000..9694475 Binary files /dev/null and b/images/search-form.png differ diff --git a/images/search-results.png b/images/search-results.png new file mode 100644 index 0000000..93319d7 Binary files /dev/null and b/images/search-results.png differ diff --git a/images/start-menu.jpg b/images/start-menu.jpg new file mode 100644 index 0000000..127509d Binary files /dev/null and b/images/start-menu.jpg differ diff --git a/images/uparrow-blue.gif b/images/uparrow-blue.gif new file mode 100644 index 0000000..0ac60ad Binary files /dev/null and b/images/uparrow-blue.gif differ diff --git a/images/uparrow-blue1.gif b/images/uparrow-blue1.gif new file mode 100644 index 0000000..bb4a8c8 Binary files /dev/null and b/images/uparrow-blue1.gif differ diff --git a/images/uparrow-blue2.gif b/images/uparrow-blue2.gif new file mode 100644 index 0000000..0ac60ad Binary files /dev/null and b/images/uparrow-blue2.gif differ diff --git a/images/uparrow-blue3.gif b/images/uparrow-blue3.gif new file mode 100644 index 0000000..7c22e03 Binary files /dev/null and b/images/uparrow-blue3.gif differ diff --git a/images/uparrow-blue4.gif b/images/uparrow-blue4.gif new file mode 100644 index 0000000..f495f3b Binary files /dev/null and b/images/uparrow-blue4.gif differ diff --git a/include/common.php b/include/common.php new file mode 100644 index 0000000..d7a9692 --- /dev/null +++ b/include/common.php @@ -0,0 +1,130 @@ + + + + PHPki: <?=$title?> + + + + +
>PHPki
+
>
+ + + "; + + if (DEMO) { + print "Public"; + print "Manage"; + } + else { + print "Menu"; + } + + if (file_exists('policy.html')) { + print 'Policy'; + } + ?> + href=help.php target=_help>Help + href=about.php target=_about>About + + "; + + if (DEMO) { + print "Public"; + print "Manage"; + } + else { + print "Menu"; + } + + if (file_exists('../policy.html')) { + print 'Policy'; + } + ?> + href=../help.php target=_help>Help + href=../about.php target=_about>About + +
+
+
+
PHPki v - Copyright 2003 - William E. Roadcap

+ + + diff --git a/include/my_functions.php b/include/my_functions.php new file mode 100644 index 0000000..138bc03 --- /dev/null +++ b/include/my_functions.php @@ -0,0 +1,208 @@ + $v) { + my_stripslashes($a[$k]); + } + } + else { + $a = stripslashes($a); + } +} + + +# +# Don't use this. +# +function undo_magic_quotes(&$a) { + if(get_magic_quotes_gpc()) { + global $HTTP_POST_VARS, $HTTP_GET_VARS; + + foreach($HTTP_POST_VARS as $k => $v) { + stripslashes_array($HTTP_POST_VARS[$k]); + global $$k; + stripslashes_array($$k); + } + foreach($HTTP_GET_VARS as $k => $v) { + stripslashes_array($HTTP_GET_VARS[$k]); + global $$k; + stripslashes_array($$k); + } + } +} + +# +# Returns TRUE if argument contains only alphabetic characters. +# +function is_alpha($v) { + return (eregi('[^A-Z]',$v) ? false : true) ; +} + +# +# Returns TRUE if argument contains only numeric characters. +# +function is_num($v) { + return (eregi('[^0-9]',$v) ? false : true) ; +} + +# +# Returns TRUE if argument contains only alphanumeric characters. +# +function is_alnum($v) { + return (eregi('[^A-Z0-9]',$v) ? false : true) ; +} + +# +# Returns TRUE if argument is in proper e-mail address format. +# +function is_email($v) { + return (eregi('^[^@ ]+\@[^@ ]+\.[A-Z]{2,4}$',$v) ? true : false); +} + +# +# Checks regexp in every element of an array, returns TRUE as soon +# as a match is found. +# +function eregi_array($regexp, $a) { + +foreach($a as $e) { + if (eregi($regexp,$e)) return true; +} +return false; +} + +# +# Reads entire file into a string +# Same as file_get_contents in php >= 4.3.0 +# +function my_file_get_contents($f) { + return implode('', file($f)); +} + +?> diff --git a/include/openssl_functions.php b/include/openssl_functions.php new file mode 100644 index 0000000..163594d --- /dev/null +++ b/include/openssl_functions.php @@ -0,0 +1,784 @@ + strtotime("$mm/$dd/$yy")) + $db['status'] = "Expired"; + + $db['serial'] = $a[3]; + $db['country'] = $b[1]; + $db['province'] = $b[2]; + $db['locality'] = $b[3]; + $db['organization'] = $b[4]; + $db['issuer'] = $b[5]; + $db['unit'] = $b[6]; + $db['common_name'] = $b[7]; + $db['email'] = $b[8]; + + return $db; +} + +// +// Returns the date & time a specified certificate is revoked, +// Returns FALSE if the certificate is not revoked. +// +function CAdb_is_revoked($serial) { + global $config; + $regexp = "^R\t.*\t.*\t$serial\t.*\t.*$"; + $x = exec('egrep '.escshellarg($regexp).' '.$config['index']); + + if ($x) { + list($j,$j,$revoke_date,$j,$j,$j) = explode("\t", $x); + sscanf($revoke_date, "%2s%2s%2s",$yy,$mm,$dd); + return strftime("%b %d, %Y", strtotime("$mm/$dd/$yy")); + } + else + return false; +} + +// +// Returns TRUE if a certificate is valid, otherwise FALSE. +// +function CAdb_is_valid($serial) { + global $config; + $regexp = "^V\t.*\t.*\t$serial\t.*\t.*$"; + + if (exec('egrep '.escshellarg($regexp).' '.$config['index'])) + return true; + else + return false; +} + +// +// Returns the long-form certificate description as output by +// openssl x509 -in certificatefile -text -purpose +// +function CA_cert_text($serial) { + global $config; + $certfile = $config['new_certs_dir'] . '/' . $serial . '.pem'; + return(shell_exec(X509.' -in '.escshellarg($certfile).' -text -purpose 2>&1')); +} + +// +// Returns the long-form text of the Certificate Revocation List +// openssl crl -in crlfile -text +// +function CA_crl_text() { + global $config; + $crlfile = $config['cacrl_pem']; + return(shell_exec(CRL.' -in '.escshellarg($crlfile).' -text 2>&1')); +} + +// +// Returns the subject of a certificate. +// +function CA_cert_subject($serial) { + global $config; + $certfile = $config['new_certs_dir'] . '/' . $serial . '.pem'; + $x = exec(X509.' -in '.escshellarg($certfile).' -noout -subject 2>&1'); + return(str_replace('subject=', '', $x)); +} + +// +// Returns the common name of a certificate. +// +function CA_cert_cname($serial) { + global $config; + return(ereg_replace('^.*/CN=(.*)/.*','\\1',CA_cert_subject($serial))); +} + +// +// Returns the email address of a certificate. +// +function CA_cert_email($serial) { + global $config; + $certfile = $config['new_certs_dir'] . '/' . $serial . '.pem'; + $x = exec(X509.' -in '.escshellarg($certfile).' -noout -email 2>&1'); + return($x); +} + +// +// Returns the effective date of a certificate. +// +function CA_cert_startdate($serial) { + global $config; + $certfile = $config['new_certs_dir'] . '/' . $serial . '.pem'; + $x = exec(X509.' -in '.escshellarg($certfile).' -noout -startdate 2>&1'); + return(str_replace('notBefore=','',$x)); +} + +// +// Returns the expiration date of a certificate. +// +function CA_cert_enddate($serial) { + global $config; + $certfile = $config['new_certs_dir'] . '/' . $serial . '.pem'; + $x = exec(X509.' -in '.escshellarg($certfile).' -noout -enddate 2>&1'); + return(str_replace('notAfter=','',$x)); +} + +// +// Revokes a specified certificate. +// +function CA_revoke_cert($serial) { + global $config; + + $fd = fopen($config['index'],'a'); + flock($fd, LOCK_EX); + + $certfile = "$config[new_certs_dir]/$serial.pem"; + + $cmd_output[] = 'Revoking the certificate.'; + exec(CA." -config '$config[openssl_cnf]' -revoke ".escshellarg($certfile)." -passin pass:'$config[ca_pwd]' 2>&1", $cmd_output, $ret); + + if ($ret == 0) { + unset($cmd_output); + list($ret, $cmd_output[]) = CA_generate_crl(); + } + + fclose($fd); + + return array(($ret == true || $ret == 0 ? true : false), implode('
',$cmd_output)); +} + +// +// Creates a new certificate request, and certificate in various formats +// according to specified parameters. PKCS12 bundle files contain the +// private key, certificate, and CA certificate. +// +// Returns an array containing the output of failed openssl commands. +// +function CA_create_cert($cert_type='email',$country,$province,$locality,$organization,$unit,$common_name,$email,$expiry,$passwd,$keysize=1024) { + global $config; + + # Wait here if another user has the database locked. + $fd = fopen($config['index'],"a"); + flock($fd, LOCK_EX); + + # Get the next available serial number + $serial = trim(implode('',file($config['serial']))); + + $userkey = $config['private_dir'].'/'.$serial.'-key.pem'; + $userreq = $config['req_dir'].'/'.$serial.'-req.pem'; + $usercert = $config['new_certs_dir'].'/'.$serial.'.pem'; + $userder = $config['cert_dir'].'/'.$serial.'.der'; + $userpfx = $config['pfx_dir'].'/'.$serial.'.pfx'; + + $expiry_days = round($expiry * 365.25, 0); + + $cnf_file = CA_create_cnf($country,$province,$locality,$organization,$unit,$common_name,$email,$keysize); + + # Escape certain dangerous characters in user input + $email = escshellcmd($email); + $_passwd = escshellarg($passwd); + $friendly_name = escshellarg($common_name); + $extensions = escshellarg($cert_type.'_ext'); + + # Create the certificate request + unset($cmd_output); + $cmd_output[] = 'Creating certifcate request.'; + + if ($passwd) { + exec(REQ." -new -newkey rsa:$keysize -keyout '$userkey' -out '$userreq' -config '$cnf_file' -days '$expiry_days' -passout pass:$_passwd 2>&1", $cmd_output, $ret); + } + else { + exec(REQ." -new -nodes -newkey rsa:$keysize -keyout '$userkey' -out '$userreq' -config '$cnf_file' -days '$expiry_days' 2>&1", $cmd_output, $ret); + } + + # Sign the certificate request and create the certificate + if ($ret == 0) { + unset($cmd_output); + $cmd_output[] = "Signing $cert_type certifcate request."; + exec(CA." -config '$cnf_file' -in '$userreq' -out /dev/null -notext -days '$expiry_days' -passin pass:'$config[ca_pwd]' -batch -extensions $extensions 2>&1", $cmd_output, $ret); + }; + + # Create DER format certificate + if ($ret == 0) { + unset($cmd_output); + $cmd_output[] = "Creating DER format certifcate."; + exec(X509." -in '$usercert' -out '$userder' -inform PEM -outform DER 2>&1", $cmd_output, $ret); + }; + + # Create a PKCS12 certificate file for download to Windows + if ($ret == 0) { + unset($cmd_output); + $cmd_output[] = "Creating PKCS12 format certifcate."; + if ($passwd) { + $cmd_output[] = "infile: $usercert keyfile: $userkey outfile: $userpfx pass: $_passwd"; + exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$config[cacert_pem]' -caname '$config[organization]' -out '$userpfx' -name $friendly_name -rand '$config[random]' -passin pass:$_passwd -passout pass:$_passwd 2>&1", $cmd_output, $ret); + } + else { + $cmd_output[] = "infile: $usercert keyfile: $userkey outfile: $userpfx"; + exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$config[cacert_pem]' -caname '$config[organization]' -out '$userpfx' -name $friendly_name -nodes -passout pass: 2>&1", $cmd_output, $ret); + } + }; + + #Unlock the CA database + fclose($fd); + + #Remove temporary openssl config file. + if (file_exists($cnf_file)) unlink($cnf_file); + + if ($ret == 0) { + # Successful! + # Return status=true and serial number of issued certificate. + return array(true, $serial); + + } + else { + # Not successful. :-( + # Clean up our loose ends. + # Return status=false and openssl output/errors for debug. + CA_remove_cert($serial); + $cmd_output[] = 'Click on the "Help" link above for information on how to report this problem.'; + return array(false, implode("
",$cmd_output)); + } +} + +// +// Renews a specified certificate, revoking any existing valid versions. +// Uses old certificate request to Creates a new request, and certificate +// in various formats. +// +// Returns an array containing the output of failed openssl commands. +// +// FIXME: Yes, I know... This functions contains much duplicative code +// from CA_create_cert(). Bleh! +// +function CA_renew_cert($old_serial,$expiry,$passwd) { + global $config; + + # Don't renew a revoked certificate if a valid one exists for this + # URL. Find and renew the valid certificate instead. + if (CAdb_is_revoked($old_serial)) { + $ret = CAdb_in(CA_cert_email($old_serial),CA_cert_cname($old_serial)); + if ($ret && $old_serial != $ret) $old_serial = $ret; + } + + # Valid certificates must be revoked prior to renewal. + if (CAdb_is_valid($old_serial)) { + $ret = CA_revoke_cert($old_serial); + if (! $ret[0]) return $ret; + } + + $cert_type = CA_cert_type($old_serial); + $extensions = $cert_type.'_ext'; + + # Get common_name from old certificate for use as the + # "friendly name" of PKCS12 certificate. + $rec = CAdb_get_entry($old_serial); + $country = $rec['country']; + $province = $rec['province']; + $locality = $rec['locality']; + $organization = $rec['organiztion']; + $unit = $rec['unit']; + $common_name = $rec['common_name']; + $email = $rec['email']; + + # Wait here if another user has the database locked. + $fd = fopen($config['index'],"a"); + flock($fd, LOCK_EX); + + # Get the next available serial number + $serial = trim(implode('',file($config['serial']))); + + $old_userkey = $config['private_dir'].'/'.$old_serial.'-key.pem'; + $old_userreq = $config['req_dir'].'/'.$old_serial.'-req.pem'; + $userkey = $config['private_dir'].'/'.$serial.'-key.pem'; + $userreq = $config['req_dir'].'/'.$serial.'-req.pem'; + $usercert = $config['new_certs_dir'].'/'.$serial.'.pem'; + $userder = $config['cert_dir'].'/'.$serial.'.der'; + $userpfx = $config['pfx_dir'].'/'.$serial.'.pfx'; + + $expiry_days = round($expiry * 365.25, 0); + + $cmd_output = array(); + $ret = 0; + + # Create a new certificate request by copying the old request. + if (! file_exists($old_userreq) || ! copy($old_userreq,$userreq)) { + $cmd_output[] = 'Could not create new certificate request file.'; + $ret = 1; + } + + # Copy private key to new file. + if ($ret == 0 && (! file_exists($old_userkey) || ! copy($old_userkey,$userkey))) { + $cmd_output[] = "Could not update private key file."; + $ret = 1; + } + + $cnf_file = CA_create_cnf($country,$province,$locality,$organization,$unit,$common_name,$email); + + # "friendly name" of PKCS12 certificate. + $friendly_name = escshellarg($rec['common_name']); + + # Escape dangerous characters in user input. + $_passwd = escshellarg($passwd); + + # Sign the certificate request and create the certificate. + if ($ret == 0) { + unset($cmd_output); + $cmd_output[] = "Signing the $cert_type certificate request."; + exec(CA." -config '$cnf_file' -in '$userreq' -out /dev/null -notext -days '$expiry_days' -passin pass:'$config[ca_pwd]' -batch -extensions $extensions 2>&1", $cmd_output, $ret); + }; + + # Create DER format certificate + if ($ret == 0) { + unset($cmd_output); + $cmd_output[] = "Creating DER format certificate."; + exec(X509." -in '$usercert' -out '$userder' -inform PEM -outform DER 2>&1", $cmd_output, $ret); + }; + + # Create a PKCS12 certificate file for download to Windows + if ($ret == 0) { + unset($cmd_output); + $cmd_output[] = "Creating PKCS12 format certificate."; + if ($passwd) { + $cmd_output[] = "infile: $usercert keyfile: $userkey outfile: $userpfx pass: $_passwd"; + exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$config[cacert_pem]' -caname '$config[organization]' -out '$userpfx' -name $friendly_name -rand '$config[random]' -passin pass:$_passwd -passout pass:$_passwd 2>&1", $cmd_output, $ret); + } + else { + $cmd_output[] = "infile: $usercert keyfile: $userkey outfile: $userpfx"; + #exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$config[cacert_pem]' -caname '$config[organization]' -out '$userpfx' -name $friendly_name -passout pass: 2>&1", $cmd_output, $ret); + exec(PKCS12." -export -in '$usercert' -inkey '$userkey' -certfile '$config[cacert_pem]' -caname '$config[organization]' -out '$userpfx' -name $friendly_name -nodes 2>&1", $cmd_output, $ret); + } + }; + + #Unlock the CA database + fclose($fd); + + #Remove temporary openssl config file. + if (file_exists($cnf_file)) unlink($cnf_file); + + if ($ret == 0) { + return array(true, $serial); + } + else { + # Not successful, so clean up before exiting. + CA_remove_cert($serial); + + if (eregi_array('.*private key.*',$cmd_output)) + $cmd_output[] = 'This was likely caused by entering the wrong certificate password.'; + else + $cmd_output[] = 'Click on the "Help" link above for information on how to report this problem.'; + + return array(false, implode('
',$cmd_output)); + } +} + +// +// Creates a new Certificate Revocation List and copies it the the approriate +// locations. Returns error messages from failed commands. +// +function CA_generate_crl() { + global $config; + + $ret = 0; + + $cmd_output[] = "Generating Certificate Revocation List."; + exec(CA. " -gencrl -config '$config[openssl_cnf]' -out '$config[cacrl_pem]' -passin pass:'$config[ca_pwd]' 2>&1", $cmd_output, $ret); + + if ($ret == 0) { + unset($cmd_output); + $cmd_output[] = "Creating DER format Certificate Revocation List."; + exec(CRL." -in '$config[cacrl_pem]' -out '$config[cacrl_der]' -inform PEM -outform DER 2>&1", $cmd_output, $ret); + } + + return array(($ret == 0 ? true : false), implode('
',$cmd_output)); +} + +// +// Removes a specified certificate from the certificate index, +// and all traces of it from the file system. +// +function CA_remove_cert($serial) { + global $config; + + $userreq = $config['req_dir'].'/'.$serial.'-req.pem'; + $userkey = $config['private_dir'].'/'.$serial.'-key.pem'; + $usercert = $config['new_certs_dir'].'/'.$serial.'.pem'; + $userder = $config['cert_dir'].'/'.$serial.'.der'; + $userpfx = $config['pfx_dir'].'/'.$serial.'.pfx'; + + + # Wait here if another user has the database locked. + $fd = fopen($config['index'],'a'); + flock($fd, LOCK_EX); + + if( file_exists($userreq)) unlink($userreq); + if( file_exists($userkey)) unlink($userkey); + if( file_exists($usercert)) unlink($usercert); + if( file_exists($userder)) unlink($userder); + if( file_exists($userpfx)) unlink($userpfx); + + $tmpfile = $config['index'].'.tmp'; + copy($config['index'], $tmpfile); + + $regexp = "^[VR]\t.*\t.*\t".$serial."\t.*\t.*$"; + exec('egrep -v '.escshellarg($regexp)." $tmpfile > $config[index] 2>/dev/null"); + + unlink($tmpfile); + fclose($fd); + +} + +// +// Returns the likely intended use for a specified certificate +// (email, server, vpn). +// +function CA_cert_type($serial) { + + $certtext = CA_cert_text($serial); + + if (ereg('OpenSSL.* (E.?mail|Personal) .*Certificate', $certtext) && ereg('Code Signing', $certtest)) { + $cert_type = 'email_signing'; + } + if (ereg('OpenSSL.* (E.?mail|Personal) .*Certificate', $certtext)) { + $cert_type = 'email'; + } + elseif (ereg('OpenSSL.* Server .*Certificate', $certtext)) { + $cert_type = 'server'; + } + elseif (ereg('timeStamping|Time Stamping', $certtext)) { + $cert_type = 'time_stamping'; + } + elseif (ereg('TLS Web Client Authentication', $certtext) && ereg('TLS Web Server Authentication', $certtext)) { + $cert_type = 'vpn_client_server'; + } + elseif (ereg('TLS Web Client Authentication', $certtext)) { + $cert_type = 'vpn_client'; + } + elseif (ereg('TLS Web Server Authentication', $certtext)) { + $cert_type = 'vpn_server'; + } + else { + $cert_type = 'vpn_client_server'; + } + + return $cert_type; +} + +function CA_get_root_pem() { + global $config; + return(file_get_contents($config['cacert_pem'])); +} + +?> diff --git a/index.php b/index.php new file mode 120000 index 0000000..42f85a9 --- /dev/null +++ b/index.php @@ -0,0 +1 @@ +readme.php \ No newline at end of file diff --git a/main.php b/main.php new file mode 100644 index 0000000..54e0fd1 --- /dev/null +++ b/main.php @@ -0,0 +1,73 @@ + +

Root Certificate (PEM Encoded)

+

+

+

+

method=post> + +
+ +
+
+
+ + + + + + + + + + + + + + + +
+

+ diff --git a/ns_revoke_query.php b/ns_revoke_query.php new file mode 100644 index 0000000..6473bf3 --- /dev/null +++ b/ns_revoke_query.php @@ -0,0 +1,27 @@ + diff --git a/openssl.cnf b/openssl.cnf new file mode 100644 index 0000000..0fdc2e2 --- /dev/null +++ b/openssl.cnf @@ -0,0 +1,183 @@ +HOME = /var/www/phpki-store +RANDFILE = /var/www/phpki-store/CA/.rnd +dir = /var/www/phpki-store/CA +certs = /var/www/phpki-store/CA/certs +crl_dir = /var/www/phpki-store/CA/crl +database = /var/www/phpki-store/CA/index.txt +new_certs_dir = /var/www/phpki-store/CA/newcerts +private_dir = /var/www/phpki-store/CA/private +serial = /var/www/phpki-store/CA/serial +certificate = /var/www/phpki-store/CA/certs/cacert.pem +crl = /var/www/phpki-store/CA/crl/cacrl.pem +private_key = /var/www/phpki-store/CA/private/cakey.pem +crl_extensions = crl_ext +default_days = 365 +default_crl_days = 30 +preserve = no +default_md = md5 + +[ ca ] +default_ca = email_cert + +[ root_cert ] +x509_extensions = root_ext +default_days = 3650 +policy = policy_supplied + +[ email_cert ] +x509_extensions = email_ext +default_days = 365 +policy = policy_supplied + +[ email_signing_cert ] +x509_extensions = email_signing_ext +default_days = 365 +policy = policy_supplied + +[ server_cert ] +x509_extensions = server_ext +default_days = 365 +policy = policy_supplied + +[ vpn_cert ] +x509_extensions = vpn_client_server_ext +default_days = 365 +policy = policy_supplied + + +[ policy_supplied ] +countryName = supplied +stateOrProvinceName = supplied +localityName = supplied +organizationName = supplied +organizationalUnitName = supplied +commonName = supplied +emailAddress = supplied + +[ root_ext ] +basicConstraints = CA:true +keyUsage = cRLSign, keyCertSign +nsCertType = sslCA, emailCA, objCA +subjectKeyIdentifier = hash +subjectAltName = email:copy +crlDistributionPoints = URI:http://www.somewhere.com/phpki/index.php?stage=dl_crl +nsComment = "PHPki/OpenSSL Generated Root Certificate Authority" +#nsCaRevocationUrl = ns_revoke_query.php? +nsCaPolicyUrl = http://www.somewhere.com/phpki/policy.html + +[ email_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = critical, emailProtection, clientAuth +nsCertType = critical, client, email +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = email:copy +issuerAltName = issuer:copy +crlDistributionPoints = URI:http://www.somewhere.com/phpki/index.php?stage=dl_crl +nsComment = "PHPki/OpenSSL Generated Personal Certificate" +nsBaseUrl = http://www.somewhere.com/phpki/ +nsRevocationUrl = ns_revoke_query.php? +#nsRenewalUrl = +nsCaPolicyUrl = http://www.somewhere.com/phpki/policy.html +#nsSslServerName = + +[ email_signing_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = critical, emailProtection, clientAuth, codeSigning +nsCertType = critical, client, email +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = email:copy +issuerAltName = issuer:copy +crlDistributionPoints = URI:http://www.somewhere.com/phpki/index.php?stage=dl_crl +nsComment = "PHPki/OpenSSL Generated Personal Certificate" +nsBaseUrl = http://www.somewhere.com/phpki/ +nsRevocationUrl = ns_revoke_query.php? +#nsRenewalUrl = +nsCaPolicyUrl = http://www.somewhere.com/phpki/policy.html +#nsSslServerName = + + +[ server_ext ] +basicConstraints = CA:false +keyUsage = critical, digitalSignature, keyEncipherment +nsCertType = critical, server +extendedKeyUsage = critical, serverAuth +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = email:copy +issuerAltName = issuer:copy +crlDistributionPoints = URI:http://www.somewhere.com/phpki/index.php?stage=dl_crl +nsComment = "PHPki/OpenSSL Generated Secure Server Certificate" +nsBaseUrl = http://www.somewhere.com/phpki/ +nsRevocationUrl = ns_revoke_query.php? +nsCaPolicyUrl = http://www.somewhere.com/phpki/policy.html + +[ vpn_client_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, clientAuth +nsCertType = critical, client +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = email:copy + +[ vpn_server_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = critical, serverAuth +nsCertType = critical, server +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = email:copy + +[ vpn_client_server_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = critical, serverAuth, clientAuth +nsCertType = critical, server, client +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = email:copy + +[ crl_ext ] +issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_name +string_mask = nombstr +req_extensions = req_ext + +[ req_name] +countryName = Country Name (2 letter code) +countryName_default = US +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = + +localityName = Locality Name (eg, city) +localityName_default = + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = + +1.organizationName = Second Organization Name (eg, company) +1.organizationName_default = + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = + +commonName = Common Name (eg, YOUR name) + +emailAddress = Email Address or Web URL + +[ req_ext ] +basicConstraints = critical, CA:false + diff --git a/policy.html b/policy.html new file mode 100644 index 0000000..47bd506 --- /dev/null +++ b/policy.html @@ -0,0 +1,14 @@ + + +Certificate Authority Issuer's Statement + + +

Certificate Authority Issuer's Statement

+

+This is a private Limited Liability certificate authority for use by member +non-profit agencies. +

+Certificate non-repudiation is achieved via identity verification by password +authorized certificate managers from each member agency. + + diff --git a/readme.php b/readme.php new file mode 100644 index 0000000..513efe0 --- /dev/null +++ b/readme.php @@ -0,0 +1,13 @@ +

READ ME

'; +print '
';
+readfile('./README');
+print '
'; +printFooter(); +?> diff --git a/search.php b/search.php new file mode 100644 index 0000000..f779353 --- /dev/null +++ b/search.php @@ -0,0 +1,140 @@ +

Certificate Details

+

(#'.htvar($serial).')
'.htvar(CA_cert_cname($serial).' <'.CA_cert_email($serial).'>').'

'; + + if ($revoke_date = CAdb_is_revoked($serial)) + print '

REVOKED '.htvar($revoke_date).'

'; + + print '
'.htvar(CA_cert_text($serial)).'
'; + break; + +case 'download': + $rec = CAdb_get_entry($serial); + upload("$config[cert_dir]/$serial.der", "$rec[common_name] ($rec[email]).cer", 'application/pkix-cert'); + break; + +case search: + printHeader('public'); + + $db = CAdb_to_array("^[${show_valid}${show_revoked}${show_expired}].*$search"); + + print ''; + if (sizeof($db) == 0) { + ?> +
+

Nothing Found

+
method=post name=form> + + + + + +
+
+ '; + print 'CERTIFICATE SEARCH RESULTS'; + + $headings = array( + status=>"Status", issued=>"Issued", expires=>"Expires", + common_name=>"User's Name", email=>"E-mail", + organization=>"Organization", unit=>"Department", + locality=>"Locality", province=>"State" + ); + + print ''; + foreach($headings as $field=>$head) { + print ''.htvar($head). ''; + } + print ''; + + foreach($db as $rec) { + $stcolor = array(Valid=>'green',Revoked=>'red',Expired=>'orange'); + + ?> + + + + + + > + + + + + ?stage=display&serial= target=_certdisp>Display + + ?stage=download&serial=>Download + '; + } + + ?> + + +
method=post name=form> + + + + + +
+ + +

Certificate Search

+
method=post name=search> + +
+ >Valid +      >Revoked +     >Expired + +
+ +

+ diff --git a/secure.sh b/secure.sh new file mode 100755 index 0000000..dec0c79 --- /dev/null +++ b/secure.sh @@ -0,0 +1,103 @@ +#! /bin/bash + +owner="`id -nu`" + +cat <$i/.htaccess +done + +cat <> ./ca/.htaccess +AuthName "Restricted Area" +AuthType Basic +AuthUserFile "$passwd_file" +require valid-user +SSLRequireSSL + +EOS + +cat < ./admin/.htaccess +AuthName "Restricted Area" +AuthType Basic +AuthUserFile "$passwd_file" +require valid-user +SSLRequireSSL +Order Allow,Deny +Allow from $subnet + +EOS + +# Start with web server getting read-only access to everything. +# Directories have sticky bits set. +find . -exec chown $owner:$group {} \; +find . ! -type d -exec chmod 640 {} \; +find . -type d -exec chmod 3750 {} \; + +echo "Done." diff --git a/setup.php b/setup.php new file mode 120000 index 0000000..8c56157 --- /dev/null +++ b/setup.php @@ -0,0 +1 @@ +setup.php-presetup \ No newline at end of file diff --git a/setup.php-presetup b/setup.php-presetup new file mode 100644 index 0000000..b0118f7 --- /dev/null +++ b/setup.php-presetup @@ -0,0 +1,886 @@ +&1",'r'); + + $line = ''; + while (! feof($handle)) { + $chr = fread($handle, 1); + $line .= $chr; + if ($chr == "\n") { + print str_replace("\n", "
\n", $line); + $line = ''; + flush(); + } + elseif (strlen($line) > $line_length) { + print $line."
\n"; + $line = ''; + flush(); + } + } + print $line."
\n"; + flush; + return; +} + +$version = PHPKI_VERSION; + +# Who does the webserver run as (apache,www-data,etc)? +$uid = posix_getuid(); +$pwdinfo = posix_getpwuid($uid); +$uname = $pwdinfo['name']; + +# Permissions on the file store. +$store_perms=0770; + +# Where are we? +$here = dirname($_SERVER['SCRIPT_FILENAME']); + +$submit = gpvar('submit'); +$stage = gpvar('stage'); + +$organization = gpvar('organization'); +$unit = gpvar('unit'); +$contact = gpvar('contact'); +$locality = gpvar('locality'); +$province = gpvar('province'); +$country = gpvar('country'); +$common_name = gpvar('common_name'); +$passwd = gpvar('passwd'); +$passwdv = gpvar('passwdv'); +$expiry = gpvar('expiry'); +$keysize = gpvar('keysize'); +$base_url = gpvar('base_url'); +$openssl_bin = gpvar('openssl_bin'); +$passwd_file = gpvar('passwd_file'); +$getting_help = gpvar('getting_help'); +$ca_prefix = gpvar('ca_prefix'); +$header_title = gpvar('header_title'); +$store_dir = gpvar('store_dir'); + +if ($base_url && substr($base_url,-1) != '/') $base_url .= '/'; + +$hidden_fields = ' + + + + + + + + + + + + + + + + + + +'; + +switch ($stage) { +case 'validate': + $er = ''; + + + if (! $country) $er .= 'Missing Country
'; + if (! $province) $er .= 'Missing State/Province
'; + if (! $locality) $er .= 'Missing Locality
'; + if (! $organization) $er .= 'Missing Organization
'; + if (! $unit) $er .= 'Missing Unit/Department
'; + if (! $contact) $er .= 'Missing Contact E-mail Address
'; + if (! $common_name) $er .= 'Missing Common Name
'; + if (! $passwd) $er .= 'Missing Certificate Password
'; + if (! $passwdv) $er .= 'Missing Certificate Password Verification "Again"
'; + if (! $header_title) $er .= 'Missing Header Title
'; + if (! $passwd_file) $er .= 'Missing User Password File Location'; + if (! $store_dir) $er .= 'Missing Storage Directory
'; + + + if ( $passwd && strlen($passwd) < 8 ) + $er .= 'Certificate password is too short.
'; + + if ( $passwd and $passwd != $passwdv ) + $er .= 'Password and password verification do not match.
'; + + if ( $email && ! is_email($contact) ) + $er .= 'E-mail address ('. htvar($contact) . ') may be invalid.
'; + + if (strpos($store_dir,$_SERVER['DOCUMENT_ROOT']) === 0) + $er .= 'Store directory must exist somewhere outside of DOCUMENT_ROOT ('.$_SERVER['DOCUMENT_ROOT'].').
'; + + if (strpos($store_dir,dirname($_SERVER['SCRIPT_FILENAME'])) === 0) + $er .= 'Store directory cannot exist within the PHPki installation directory ('.dirname($_SERVER['SCRIPT_FILENAME']).').
'; + + if (! $er) { + if (! file_exists($store_dir) ) { + if ( ! mkdir("$store_dir",$store_perms)) $er .= "Could not create the store directory \"$store_dir\"
"; + } + + if (file_exists($store_dir)) { + if (! chmod($store_dir, $store_perms)) $er .= "Could not change permissions on the store directory \"$store_dir\"
"; + if (! is_readable($store_dir)) $er .= "The store directory \"$store_dir\" is not readable by the web server user \"$uname\"
"; + if (! is_writeable($store_dir)) $er .= "The store directory \"$store_dir\: is not writeable by the web server user \"$uname\"
"; + } + else { + $er .= "Store directory \"$store_dir\" does not exist. You will have to manually create it as desribed in the setup form.
"; + } + } + + if ( $er ) + $er = '

ERROR(S) IN FORM:

' . $er . '

'; + + if ($er) { + printHeader('setup'); + ?> + +
+ + +
+ + "; + + printFooter(); + break; + } + +case 'write': + + printHeader('about'); + + # + #Create the file store directory structure. + # + + print 'Creating PHPki file store...
'; + flush(); + + if (! file_exists("$store_dir/config")) mkdir("$store_dir/config",$store_perms); + if (! file_exists("$store_dir/tmp")) mkdir("$store_dir/tmp",$store_perms); + if (! file_exists("$store_dir/CA")) mkdir("$store_dir/CA",$store_perms); + if (! file_exists("$store_dir/CA/certs")) mkdir("$store_dir/CA/certs",$store_perms); + if (! file_exists("$store_dir/CA/private")) mkdir("$store_dir/CA/private",$store_perms); + if (! file_exists("$store_dir/CA/newcerts")) mkdir("$store_dir/CA/newcerts",$store_perms); + if (! file_exists("$store_dir/CA/requests")) mkdir("$store_dir/CA/requests",$store_perms); + if (! file_exists("$store_dir/CA/crl")) mkdir("$store_dir/CA/crl",$store_perms); + if (! file_exists("$store_dir/CA/pfx")) mkdir("$store_dir/CA/pfx",$store_perms); + + + # + # Create the PHPki CA configuration. + # + print 'Writing configuration files...
'; + flush(); + + $config_txt = << +EOS; + + # + # Write out the CA configuration file. + # + $fd = fopen("$store_dir/config/config.php",'w'); + fwrite($fd, $config_txt); + fclose($fd); + + + # + # Create the bootstrap configuration + # + $config_txt = << +EOS; + + # + # Write out the bootstrap config + # + $fd = fopen('./config.php','w'); + fwrite($fd, $config_txt); + fclose($fd); + + + # Re-read the CA config file so the openssl_functions + # can be used to create a CA root certificate. + include("$store_dir/config/config.php"); + + # + # Now create a temporary openssl.cnf for creating a self-signed + # CA root certificate, and create a generic openssl.cnf file + # in the CA home + # + $config_txt1 = <<< EOS +HOME = $config[home_dir] +RANDFILE = $config[random] +dir = $config[ca_dir] +certs = $config[cert_dir] +crl_dir = $config[crl_dir] +database = $config[index] +new_certs_dir = $config[new_certs_dir] +private_dir = $config[private_dir] +serial = $config[serial] +certificate = $config[cacert_pem] +crl = $config[cacrl_pem] +private_key = $config[cakey] +crl_extensions = crl_ext +default_days = 365 +default_crl_days = 30 +preserve = no +default_md = md5 + +[ ca ] +default_ca = email_cert + +[ root_cert ] +x509_extensions = root_ext +default_days = 3650 +policy = policy_supplied + +[ email_cert ] +x509_extensions = email_ext +default_days = 365 +policy = policy_supplied + +[ email_signing_cert ] +x509_extensions = email_signing_ext +default_days = 365 +policy = policy_supplied + +[ server_cert ] +x509_extensions = server_ext +default_days = 365 +policy = policy_supplied + +[ vpn_cert ] +x509_extensions = vpn_client_server_ext +default_days = 365 +policy = policy_supplied + +[ time_stamping_cert ] +x509_extensions = time_stamping_ext +default_days = 365 +policy = policy_supplied + +[ policy_supplied ] +countryName = supplied +stateOrProvinceName = supplied +localityName = supplied +organizationName = supplied +organizationalUnitName = supplied +commonName = supplied +emailAddress = supplied + +[ root_ext ] +basicConstraints = CA:true +keyUsage = cRLSign, keyCertSign +nsCertType = sslCA, emailCA, objCA +subjectKeyIdentifier = hash +subjectAltName = email:copy +crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl +nsComment = "PHPki/OpenSSL Generated Root Certificate Authority" +#nsCaRevocationUrl = ns_revoke_query.php? +nsCaPolicyUrl = $config[base_url]policy.html + +[ email_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = critical, emailProtection, clientAuth +nsCertType = critical, client, email +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = email:copy +issuerAltName = issuer:copy +crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl +nsComment = "PHPki/OpenSSL Generated Personal Certificate" +nsBaseUrl = $config[base_url] +nsRevocationUrl = ns_revoke_query.php? +#nsRenewalUrl = +nsCaPolicyUrl = $config[base_url]policy.html +#nsSslServerName = + +[ email_signing_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = critical, emailProtection, clientAuth, codeSigning +nsCertType = critical, client, email +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = email:copy +issuerAltName = issuer:copy +crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl +nsComment = "PHPki/OpenSSL Generated Personal Certificate" +nsBaseUrl = $config[base_url] +nsRevocationUrl = ns_revoke_query.php? +#nsRenewalUrl = +nsCaPolicyUrl = $config[base_url]policy.html +#nsSslServerName = + +[ server_ext ] +basicConstraints = CA:false +keyUsage = critical, digitalSignature, keyEncipherment +nsCertType = critical, server +extendedKeyUsage = critical, serverAuth, 1.3.6.1.5.5.7.3.1 +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = DNS:$common_name,email:copy +issuerAltName = issuer:copy +crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl +nsComment = "PHPki/OpenSSL Generated Secure Server Certificate" +nsBaseUrl = $config[base_url] +nsRevocationUrl = ns_revoke_query.php? +nsCaPolicyUrl = $config[base_url]policy.html + +[ time_stamping_ext ] +basicConstraints = CA:false +keyUsage = critical, nonRepudiation, digitalSignature +extendedKeyUsage = timeStamping +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = DNS:$common_name,email:copy +issuerAltName = issuer:copy +crlDistributionPoints = URI:$config[base_url]index.php?stage=dl_crl +nsComment = \"PHPki/OpenSSL Generated Time Stamping Certificate\" +nsBaseUrl = $config[base_url] +nsRevocationUrl = ns_revoke_query.php? +nsCaPolicyUrl = $config[base_url]policy.html + + +[ vpn_client_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, clientAuth +nsCertType = critical, client +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = DNS:$common_name,email:copy + +[ vpn_server_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = critical, serverAuth +nsCertType = critical, server +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = DNS:$common_name,email:copy + +[ vpn_client_server_ext ] +basicConstraints = critical, CA:false +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = critical, serverAuth, clientAuth +nsCertType = critical, server, client +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always, issuer:always +subjectAltName = DNS:$common_name,email:copy + +[ crl_ext ] +issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + + +EOS; + + $config_txt2 = <<< EOS +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_name +string_mask = nombstr +req_extensions = req_ext + +[ req_name] +countryName = Country Name (2 letter code) +countryName_default = US +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = + +localityName = Locality Name (eg, city) +localityName_default = + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = + +1.organizationName = Second Organization Name (eg, company) +1.organizationName_default = + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = + +commonName = Common Name (eg, YOUR name) + +emailAddress = Email Address or Web URL + +[ req_ext ] +basicConstraints = critical, CA:false + + +EOS; + + $config_txt3 = <<< EOS +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_name +string_mask = nombstr +req_extensions = req_ext +prompt = no + +[ req_name ] +C = $config[country] +ST = $config[province] +L = $config[locality] +O = $config[organization] +OU = $config[unit] +CN = $config[common_name] +emailAddress = $config[contact] + +[ req_ext ] +basicConstraints = critical, CA:true + + +EOS; + + # + # Write the permanent OpenSSL config + # + $fd = fopen($config['openssl_cnf'],'w'); + fwrite($fd, $config_txt1 . $config_txt2); + fclose($fd); + + # + # Write the temporary OpenSSL config + # + $tmp_cnf = "$config[home_dir]/tmp/openssl.cnf"; + $fd = fopen($tmp_cnf,'w'); + fwrite($fd, $config_txt1 . $config_txt3); + fclose($fd); + + # + # Intialize index.txt and serial files + # + $fd = fopen($config['index'],'w'); + fwrite($fd, ""); + fclose($fd); + # + $fd = fopen($config['serial'],'w'); + fwrite($fd, "100001"); + fclose($fd); + + # + # Convert expiry years to approximate days. + # + $days = $config['expiry'] * 365.25; + + + # + # Create a new self-signed CA certificate in PEM format. + # + print 'Creating root certificate...
'; + flush(); + + exec(REQ . " -x509 -config $tmp_cnf -extensions root_ext -newkey rsa:$keysize -keyout $config[cakey] -out $config[cacert_pem] -passout pass:'$config[ca_pwd]' -days $days 2>&1"); + + # **** DISABLED ***** + # It appears that both IE and Netscape accept PEM formatted root certificates + # + # Create a copy of the CA certificate in DER format. + # + #exec(X509 . " -in ca/$config[cacert_pem] -inform PEM -out ca/$config[cacert_der] -outform DER 2>&1"); + + # + # Generate the initial CRL. + # + print 'Generating certificate revocation list...
'; + flush(); + exec(CA . " -gencrl -config $config[openssl_cnf] -out $config[cacrl_pem] -passin pass:'$config[ca_pwd]'"); + + # Make a copy of the CRL in DER format. + # + exec(CRL . " -in $config[cacrl_pem] -out $config[cacrl_der] -inform PEM -outform DER"); + + # + # Clean up. + # + if (! unlink("$store_dir/tmp/openssl.cnf")) print "Can't unlink $store_dir/tmp/openssl.cnf"; + + + # + # Create dhparam files for OpenVPN and others. + # + print '

Creating 1024 bit Diffie-Hellman parameters used by OpenVPN.
'; + print "Saving to $store_dir/dhparam1024.pem.

"; + $cmd = "openssl dhparam -rand '$config[random]' -out '$config[private_dir]/dhparam1024.pem' 1024"; + print $cmd.'
'; + flush(); + flush_exec($cmd,100); + + + #print '

Creating 2048 bit Diffie-Hellman parameters used by OpenVPN.
'; + #print "Saving to $store_dir/dhparam2048.pem.

"; + #$cmd = "openssl dhparam -rand '$config[random]' -out '$config[private_dir]/dhparam2048.pem' 2048"; + #print $cmd.'
'; + #flush(); + #flush_exec($cmd,200); + + # + # Step aside and let the users in (create index.php files). + # + if (! unlink('index.php')) print "Can't unlink index.php"; + if (! unlink('setup.php')) print "Can't unlink setup.php";; + if (! unlink('ca/index.php')) print "Can't unlink ca/index.php"; + if (! symlink('main.php','index.php')) print "Can't symlink main.php"; + if (! symlink('main.php','ca/index.php')) print "Can't symlink ca/main.php";; + + ?> +

+

Setup is complete. Your CA root certificate as been created.

+

SECURITY WARNING!   Be sure to run the secure.sh shell script as the root user.

+



+ + +

+
+ Contact:
+First-Name Last-Name
+Company/Organization Name
+Address Line #1
+Address Line #2
+City, State, ZipCode
+
+Phone: (000) 000-0000
+E-mail: someone@somewhere.com   E-mail is preferred.
'; + + if (! $store_dir) $store_dir = dirname($_SERVER['DOCUMENT_ROOT']).'/phpki-store'; + + if (! $base_url) $base_url = $config['base_url']; + if (! $base_url) $base_url = 'http://www.somewhere.com/phpki/'; + + if (! $ca_prefix) $ca_prefix = $config['ca_prefix']; + + if (! $openssl_bin) $openssl_bin = $config['openssl_bin']; + if (! $openssl_bin) $openssl_bin = '/usr/bin/openssl'; + + if (! $passwd_file) $passwd_file = $config['passwd_file']; + if (! $passwd_file) $passwd_file = dirname($_SERVER['DOCUMENT_ROOT']).'/phpkipasswd'; + + if (! $header_title) $header_title = $config['header_title']; + if (! $header_title) $header_title = 'Certificate Authority'; + + printHeader('setup'); + ?> +
method=post> +

Certificate Authority Initial Setup

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Root Certificate Data

Organization *
Department/Unit *
+ Common Name * + This is embeded in certificates, and is most often displayed in + e-mail clients as the Issued By: text. This is usually + the full name of your certificate authority (i.e. ACME Certificate Authority). +
+ Technical Contact E-mail Address *
+ Enter an e-mail address where users should send correspondence + regarding your certificate authority and the certificates you issue. +
Locality *
State/Province *
Country *
+ Password *
+ This password will be used to protect your root certificate private + key. Do not lose or forget this password. +
   Again
+ Certificate Life *
+ Enter the number of years you wish your root certificate to be valid. +
+ Key Size *
+ Enter the size of your certificate key. +
+ Certificate Authority Base URL
+ Enter the public Web address where your Certificate Authority will + reside. The address should end with a trailing slash (/) character. + This address will be embeded in all certficates issued + by your CA, for informational purposes. +
+ +
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Configuration Options

+ Storage Directory *
+ Enter the location where PHPki will store its files. This should be a directory where + the web server has full read/write access (chown ; chmod 700), and is preferably + outside of DOCUMENT_ROOT (). You may have to manually create the directory before completing this form. +
+ +
+ Location of OpenSSL Executable *
+ Enter the location of your OpenSSL binary. The default is usually ok. +
+ +
+ Location of HTTP password file *
+ Enter the location of your PHPki user password file. The default is usually ok. +
+ +
+ File Upload Prefix
+ This is an optional prefix which will be added to root certificate + and certificate revocation list file uploads. Normally the root + certificate is uploaded as caroot.crt. With a prefix like + "acme_", the root certificate would be uploaded as + "acme_caroot.crt". +
+ +
+ Page Header Title
+ This title will be displayed superimposed over the PHPki logo at the + top of every page. +
+ +
+ Help Document Contact Info
+ This text will be inserted into the online help document + under the "Getting Additional Help" section. Include full + contact info for the convenience of your users. Use HTML + tags to improve presentation. +
+ +
+ * Required field + +

+

+ +
+ +