summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-06-02 02:41:47 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2012-06-02 02:41:47 -0500
commited617ebffea2ac94d4a368b876f2a6414af0bbb3 (patch)
tree1d5f16ed2e663590ebfcfffa2fd2652ccec5131d /src
parent7df2e830ef2d9005a27e0a295988fece9911c0f5 (diff)
downloadkcmldapcontroller-ed617ebffea2ac94d4a368b876f2a6414af0bbb3.tar.gz
kcmldapcontroller-ed617ebffea2ac94d4a368b876f2a6414af0bbb3.zip
OpenLDAP now initializes, but login is not possible and kadmin does not work yet
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/ldapcontroller.cpp195
-rw-r--r--src/ldapcontroller.h13
-rw-r--r--src/realmfinishpage.cpp5
-rw-r--r--src/realmfinishpagedlg.ui17
-rw-r--r--src/realmwizard.cpp3
-rw-r--r--src/sha1.cc433
-rw-r--r--src/sha1.h74
8 files changed, 730 insertions, 12 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ad0fd3..5aa0043 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,7 +4,7 @@ METASOURCES = AUTO
# Install this plugin in the KDE modules directory
kde_module_LTLIBRARIES = kcm_ldapcontroller.la
-kcm_ldapcontroller_la_SOURCES = ldapcontroller.cpp ldapcontrollerconfigbase.ui realmwizard.cpp realmintropagedlg.ui realmintropage.cpp realmconfigpagedlg.ui realmconfigpage.cpp realmfinishpagedlg.ui realmfinishpage.cpp processingdialog.cpp
+kcm_ldapcontroller_la_SOURCES = ldapcontroller.cpp ldapcontrollerconfigbase.ui realmwizard.cpp realmintropagedlg.ui realmintropage.cpp realmconfigpagedlg.ui realmconfigpage.cpp realmfinishpagedlg.ui realmfinishpage.cpp processingdialog.cpp sha1.cc
kcm_ldapcontroller_la_LIBADD = -lkio $(LIB_TDEUI)
kcm_ldapcontroller_la_LDFLAGS = -avoid-version -module -no-undefined \
$(all_libraries)
diff --git a/src/ldapcontroller.cpp b/src/ldapcontroller.cpp
index 0b30db9..427148b 100644
--- a/src/ldapcontroller.cpp
+++ b/src/ldapcontroller.cpp
@@ -41,6 +41,9 @@
#include <kmessagebox.h>
#include <tqcheckbox.h>
#include <ktempdir.h>
+#include <kprocess.h>
+
+#include "sha1.h"
#include "ldapcontroller.h"
#include "realmwizard.h"
@@ -225,11 +228,109 @@ void LDAPController::save() {
load();
}
-void replacePlaceholdersInFile(TQString infile, TQString outfile) {
+void replacePlaceholdersInFile(TQString infile, TQString outfile, LDAPRealmConfig realmconfig, TQString adminUserName, TQString adminGroupName, const char * adminPassword, TQString rootUserName, const char * rootPassword, int ldifSchemaNumber=-1, uid_t userid=-1, gid_t groupid=-1) {
+ SHA1 sha;
+ sha.process(rootPassword, strlen(rootPassword));
+ TQString rootpw_hash = sha.base64Hash();
+ sha.reset();
+ sha.process(adminPassword, strlen(rootPassword));
+ TQString adminpw_hash = sha.base64Hash();
+
// RAJA FIXME
+
+ // Created needed strings
+ TQStringList domainChunks = TQStringList::split(".", realmconfig.name.lower());
+ TQString basedcname = "dc=" + domainChunks.join(",dc=");
+ TQString simpledcname = domainChunks[0];
+ TQString simpledcnamecap = simpledcname.lower();
+ simpledcnamecap[0] = simpledcnamecap[0].upper();
+ TQString timestamp = TQDateTime::currentDateTime().toString(TQt::ISODate);
+ timestamp.replace("-", "");
+ timestamp.replace(":", "");
+ timestamp.replace("T", "");
+
+ TQFile ifile(infile);
+ TQFile ofile(outfile);
+ if (ifile.open(IO_ReadOnly) && ofile.open(IO_WriteOnly)) {
+ TQString line;
+ TQTextStream istream(&ifile);
+ TQTextStream ostream(&ofile);
+ while (!istream.atEnd()) {
+ line = istream.readLine();
+ line.replace("@@@REALM_DCNAME@@@", basedcname);
+ line.replace("@@@REALM_UCNAME@@@", realmconfig.name.upper());
+ line.replace("@@@REALM_LCNAME@@@", realmconfig.name.lower());
+ line.replace("@@@ADMINSERVER@@@", realmconfig.admin_server);
+ line.replace("@@@ADMINPORT@@@", TQString("%1").arg(realmconfig.admin_server_port));
+ line.replace("@@@KDCSERVER@@@", realmconfig.kdc);
+ line.replace("@@@KDCPORT@@@", TQString("%1").arg(realmconfig.kdc_port));
+ line.replace("@@@ROOTUSER@@@", rootUserName);
+ line.replace("@@@ROOTPW_SHA@@@", rootpw_hash);
+ line.replace("@@@ADMINUSER@@@", adminUserName);
+ line.replace("@@@ADMINGROUP@@@", adminGroupName);
+ line.replace("@@@ADMINPW_SHA@@@", adminpw_hash);
+ line.replace("@@@PKINIT_REQUIRE_EKU@@@", (realmconfig.pkinit_require_eku)?"yes":"no");
+ line.replace("@@@PKINIT_REQUIRE_KRBTGT_OTHERNAME@@@", (realmconfig.pkinit_require_krbtgt_otherName)?"yes":"no");
+ line.replace("@@@WIN2K_PKINIT@@@", (realmconfig.win2k_pkinit)?"yes":"no");
+ line.replace("@@@WIN2K_PKINIT_REQUIRE_BINDING@@@", (realmconfig.win2k_pkinit_require_binding)?"yes":"no");
+ line.replace("@@@REALM_SIMPLE_CP_NAME@@@", simpledcnamecap);
+ line.replace("@@@REALM_SIMPLE_LC_NAME@@@", simpledcname.lower());
+ line.replace("@@@TIMESTAMP@@@", timestamp);
+ if (ldifSchemaNumber >= 0) {
+ line.replace("@@@LDIFSCHEMANUMBER@@@", TQString("%1").arg(ldifSchemaNumber));
+ }
+ ostream << line << "\n";
+ }
+ ifile.close();
+ ofile.close();
+ }
+
+ // Set permissions
+ if ((userid > 0) && (groupid > 0)) {
+ chown(outfile.ascii(), userid, groupid);
+ }
+
+ // Keep UI responsive
+ tqApp->processEvents();
}
-int LDAPController::createNewLDAPRealm(TQWidget* dialogparent, LDAPRealmConfig realmconfig, TQString adminUserName, const char * adminPassword, TQString adminRealm, TQString *errstr) {
+int LDAPController::controlLDAPServer(sc_command command, uid_t userid, gid_t groupid) {
+ if (command == SC_START) {
+ // FIXME
+ // This assumes Debian!
+ return system("/etc/init.d/slapd start");
+ }
+ if (command == SC_STOP) {
+ // FIXME
+ // This assumes Debian!
+ return system("/etc/init.d/slapd stop");
+ }
+ if (command == SC_RESTART) {
+ // FIXME
+ // This assumes Debian!
+ return system("/etc/init.d/slapd restart");
+ }
+ if (command == SC_PURGE) {
+ controlLDAPServer(SC_STOP);
+ // FIXME
+ // This assumes Debian!
+ system("rm -rf /var/lib/ldap/*");
+ }
+ if (command == SC_SETDBPERMS) {
+ if ((userid > 0) && (groupid > 0)) {
+ TQString command;
+ command = TQString("chown -R %1 /var/lib/ldap/*").arg(userid);
+ system(command.ascii());
+ command = TQString("chgrp -R %1 /var/lib/ldap/*").arg(groupid);
+ system(command.ascii());
+ }
+ }
+ return -2;
+}
+
+int LDAPController::createNewLDAPRealm(TQWidget* dialogparent, LDAPRealmConfig realmconfig, TQString adminUserName, TQString adminGroupName, const char * adminPassword, TQString rootUserName, const char * rootPassword, TQString adminRealm, TQString *errstr) {
+ int ldifSchemaNumber;
+
ProcessingDialog pdialog(dialogparent);
pdialog.setStatusMessage(i18n("Loading data for realm deployment..."));
pdialog.raise();
@@ -237,16 +338,100 @@ int LDAPController::createNewLDAPRealm(TQWidget* dialogparent, LDAPRealmConfig r
tqApp->processEvents();
// Find the templates
- TQString templateDir = locate("data", "kcmldapcontroller/skel");
-printf("[RAJA DEBUG 100.0] templateDir: %s\n\r", templateDir.ascii()); fflush(stdout);
+ TQString templateDir = locate("data", "kcmldapcontroller/skel/heimdal/heimdal.defaults");
+ templateDir.replace("heimdal/heimdal.defaults", "");
if (templateDir == "") {
+ if (errstr) *errstr = i18n("Unable to locate required template files");
pdialog.closeDialog();
return -1;
}
KTempDir configTempDir;
configTempDir.setAutoDelete(true);
- replacePlaceholdersInFile(templateDir + "heimdal/heimdal.defaults", configTempDir.name() + "heimdal/heimdal.defaults");
+configTempDir.setAutoDelete(false); // RAJA DEBUG ONLY
+ TQString destDir = "/etc/";
+
+ mkdir(TQString(destDir + "heimdal").ascii(), S_IRUSR|S_IWUSR|S_IXUSR);
+ mkdir(TQString(destDir + "openldap").ascii(), S_IRUSR|S_IWUSR|S_IXUSR);
+ mkdir(TQString(destDir + "openldap/ldap").ascii(), S_IRUSR|S_IWUSR|S_IXUSR);
+
+ replacePlaceholdersInFile(templateDir + "heimdal/heimdal.defaults", destDir + "heimdal.defaults", realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword);
+ replacePlaceholdersInFile(templateDir + "heimdal/kadmind.acl", destDir + "kadmind.acl", realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword);
+ replacePlaceholdersInFile(templateDir + "heimdal/kdc.conf", destDir + "kdc.conf", realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword);
+ replacePlaceholdersInFile(templateDir + "heimdal/krb5.conf", destDir + "krb5.conf", realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword);
+
+ replacePlaceholdersInFile(templateDir + "openldap/skel.ldif", configTempDir.name() + "skel.ldif", realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword);
+ replacePlaceholdersInFile(templateDir + "openldap/ldap/slapd.conf", destDir + "ldap/slapd.conf", realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword);
+ replacePlaceholdersInFile(templateDir + "openldap/ldap/slapd.defaults", destDir + "ldap/slapd.defaults", realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword);
+
+ struct stat sb;
+ uid_t slapd_uid = 0;
+ gid_t slapd_gid = 0;
+ if (stat(destDir + "ldap/slapd.d/cn=config/cn=schema", &sb) == 0) {
+ slapd_uid = sb.st_uid;
+ slapd_gid = sb.st_gid;
+ }
+
+ // Base database configuration
+ ldifSchemaNumber = 1;
+ replacePlaceholdersInFile(templateDir + "openldap/ldif/olcDatabase.ldif", destDir + "ldap/slapd.d/cn=config/" + TQString("olcDatabase={%1}hdb.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid);
+
+ // Schema files
+ ldifSchemaNumber = 10;
+ replacePlaceholdersInFile(templateDir + "openldap/ldif/ems-core.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}ems-core.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid);
+ ldifSchemaNumber = 11;
+ replacePlaceholdersInFile(templateDir + "openldap/ldif/hdb.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}hdb.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid);
+ ldifSchemaNumber = 12;
+ replacePlaceholdersInFile(templateDir + "openldap/ldif/tde-core.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}tde-core.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid);
+
+ // Set permissions
+ chmod(TQString(destDir + "heimdal.defaults").ascii(), S_IRUSR|S_IWUSR|S_IRGRP);
+ chmod(TQString(destDir + "kadmind.acl").ascii(), S_IRUSR|S_IWUSR|S_IRGRP);
+ chmod(TQString(destDir + "kdc.conf").ascii(), S_IRUSR|S_IWUSR|S_IRGRP);
+ chmod(TQString(destDir + "krb5.conf").ascii(), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+
+ chmod(TQString(configTempDir.name() + "skel.ldif").ascii(), S_IRUSR|S_IWUSR);
+ chmod(TQString(destDir + "ldap/slapd.conf").ascii(), S_IRUSR|S_IWUSR);
+ chmod(TQString(destDir + "ldap/slapd.defaults").ascii(), S_IRUSR|S_IWUSR|S_IRGRP);
+
+ pdialog.setStatusMessage(i18n("Purging existing LDAP database..."));
+ tqApp->processEvents();
+ controlLDAPServer(SC_PURGE);
+
+ pdialog.setStatusMessage(i18n("Loading initial database into LDAP..."));
+ tqApp->processEvents();
+
+ // Stop slapd
+ if (controlLDAPServer(SC_STOP) != 0) {
+ if (errstr) *errstr = i18n("Unable to stop LDAP server");
+ pdialog.closeDialog();
+ return -1;
+ }
+
+ // Load database
+ KProcess slapadd;
+ slapadd << "slapadd" << "-l" << configTempDir.name() + "skel.ldif";
+ slapadd.start();
+ while (slapadd.isRunning()) {
+ tqApp->processEvents();
+ }
+ if (slapadd.exitStatus() != 0) {
+ if (errstr) *errstr = i18n("Unable to import initial database into LDAP");
+ pdialog.closeDialog();
+ return -1;
+ }
+
+ controlLDAPServer(SC_SETDBPERMS, slapd_uid, slapd_gid);
+
+ pdialog.setStatusMessage(i18n("Starting LDAP server..."));
+ tqApp->processEvents();
+
+ // Start slapd
+ if (controlLDAPServer(SC_START) != 0) {
+ if (errstr) *errstr = i18n("Unable to start LDAP server");
+ pdialog.closeDialog();
+ return -1;
+ }
// RAJA FIXME
pdialog.closeDialog();
diff --git a/src/ldapcontroller.h b/src/ldapcontroller.h
index b09a46c..f5bd2a7 100644
--- a/src/ldapcontroller.h
+++ b/src/ldapcontroller.h
@@ -32,6 +32,14 @@
#include "ldapcontrollerconfigbase.h"
+enum sc_command {
+ SC_START,
+ SC_STOP,
+ SC_RESTART,
+ SC_PURGE,
+ SC_SETDBPERMS
+};
+
// PRIVATE
class LDAPRealmConfig
{
@@ -67,7 +75,7 @@ class LDAPController: public KCModule
virtual const KAboutData *aboutData() const { return myAboutData; };
public:
- int createNewLDAPRealm(TQWidget* dialogparent, LDAPRealmConfig realmconfig, TQString adminUserName, const char * adminPassword, TQString adminRealm, TQString *errstr);
+ int createNewLDAPRealm(TQWidget* dialogparent, LDAPRealmConfig realmconfig, TQString adminUserName, TQString adminGroupName, const char * adminPassword, TQString rootUserName, const char * rootPassword, TQString adminRealm, TQString *errstr);
// FIXME
// This should be moved to a TDE core library
@@ -78,6 +86,9 @@ class LDAPController: public KCModule
void processLockouts();
private:
+ int controlLDAPServer(sc_command command, uid_t userid=-1, gid_t groupid=-1);
+
+ private:
KAboutData *myAboutData;
LDAPControllerConfigBase *m_base;
diff --git a/src/realmfinishpage.cpp b/src/realmfinishpage.cpp
index c71fc0b..f2fd1b6 100644
--- a/src/realmfinishpage.cpp
+++ b/src/realmfinishpage.cpp
@@ -43,6 +43,7 @@ RealmFinishPage::RealmFinishPage(TQWidget *parent, const char *name ) : RealmFin
px_introSidebar->setPixmap(UserIcon("step3.png"));
connect(ldapAdminUsername, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(validateEntries()));
+ connect(ldapAdminGroupname, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(validateEntries()));
m_parentWizard = dynamic_cast<KWizard*>(parent);
m_parentDialog = dynamic_cast<KDialogBase*>(parent);
@@ -54,7 +55,7 @@ RealmFinishPage::~RealmFinishPage(){
void RealmFinishPage::validateEntries() {
if (m_parentWizard) {
- if (ldapAdminUsername->text() != "") {
+ if ((ldapAdminUsername->text() != "") && (ldapAdminGroupname->text() != "")) {
m_parentWizard->finishButton()->setEnabled(true);
}
else {
@@ -62,7 +63,7 @@ void RealmFinishPage::validateEntries() {
}
}
if (m_parentDialog) {
- if (ldapAdminUsername->text() != "") {
+ if ((ldapAdminUsername->text() != "") && (ldapAdminGroupname->text() != "")) {
m_parentDialog->enableButton(KDialogBase::Ok, true);
}
else {
diff --git a/src/realmfinishpagedlg.ui b/src/realmfinishpagedlg.ui
index 121e632..5cd11d6 100644
--- a/src/realmfinishpagedlg.ui
+++ b/src/realmfinishpagedlg.ui
@@ -99,15 +99,28 @@
<cstring>unnamed</cstring>
</property>
<property name="text">
- <string>LDAP Realm</string>
+ <string>Administration Group</string>
</property>
</widget>
<widget class="KLineEdit" row="5" column="2">
<property name="name">
+ <cstring>ldapAdminGroupname</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="6" column="1">
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="text">
+ <string>LDAP Realm</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="6" column="2">
+ <property name="name">
<cstring>ldapAdminRealm</cstring>
</property>
</widget>
- <spacer row="6" column="1">
+ <spacer row="7" column="1">
<property name="name">
<cstring>Spacer6</cstring>
</property>
diff --git a/src/realmwizard.cpp b/src/realmwizard.cpp
index a8c9b81..fa720c2 100644
--- a/src/realmwizard.cpp
+++ b/src/realmwizard.cpp
@@ -202,7 +202,8 @@ void RealmWizard::accept() {
// Try to create realm
TQString errorString;
// RAJA FIXME
- if (m_controller->createNewLDAPRealm(this, m_realmconfig, finishpage->ldapAdminUsername->text(), finishpage->ldapAdminPassword->password(), finishpage->ldapAdminRealm->text(), &errorString) == 0) {
+ // root account should not be locked to "admin"!
+ if (m_controller->createNewLDAPRealm(this, m_realmconfig, finishpage->ldapAdminUsername->text(), finishpage->ldapAdminGroupname->text(), finishpage->ldapAdminPassword->password(), "admin", finishpage->ldapAdminPassword->password(), finishpage->ldapAdminRealm->text(), &errorString) == 0) {
done(0);
}
else {
diff --git a/src/sha1.cc b/src/sha1.cc
new file mode 100644
index 0000000..3f5dbd9
--- /dev/null
+++ b/src/sha1.cc
@@ -0,0 +1,433 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 George Staikos <staikos@kde.org>
+ Based heavily on SHA1 code from GPG 1.0.3 (C) 1998 FSF
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h> /* For uintXX_t on OSX */
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h> /* For uintXX_t on Tru64 */
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include "sha1.h"
+#include <string.h>
+
+// FIXME: this can be optimized to one instruction on most cpus.
+#define rol(x,y) ((x << y) | (x >> (32-y)))
+
+
+#define K1 0x5a827999L
+#define K2 0x6ed9eba1L
+#define K3 0x8f1bbcdcL
+#define K4 0xca62c1d6L
+#define F1(x,y,z) ( z ^ ( x & ( y ^ z ) ) )
+#define F2(x,y,z) ( x ^ y ^ z )
+#define F3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) )
+#define F4(x,y,z) ( x ^ y ^ z )
+
+#define M(i) ( tm = x[i&0x0f] ^ x[(i-14)&0x0f] \
+ ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \
+ , (x[i&0x0f] = (tm << 1) | (tm >> 31)))
+
+#define R(a,b,c,d,e,f,k,m) do { e += rol(a, 5) \
+ + f(b, c, d) \
+ + k \
+ + m; \
+ b = rol(b, 30); \
+ } while(0)
+
+const char Base64EncMap[64] =
+{
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
+ 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
+ 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
+};
+
+void base64Encode( const TQByteArray& in, TQByteArray& out, bool insertLFs )
+{
+ // clear out the output buffer
+ out.resize (0);
+ if ( in.isEmpty() )
+ return;
+
+ unsigned int sidx = 0;
+ unsigned int didx = 0;
+ const char* data = in.data();
+ const unsigned int len = in.size();
+
+ unsigned int out_len = ((len+2)/3)*4;
+
+ // Deal with the 76 characters or less per
+ // line limit specified in RFC 2045 on a
+ // pre request basis.
+ insertLFs = (insertLFs && out_len > 76);
+ if ( insertLFs )
+ out_len += ((out_len-1)/76);
+
+ int count = 0;
+ out.resize( out_len );
+
+ // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
+ if ( len > 1 )
+ {
+ while (sidx < len-2)
+ {
+ if ( insertLFs )
+ {
+ if ( count && (count%76) == 0 )
+ out[didx++] = '\n';
+ count += 4;
+ }
+ out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
+ out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out[didx++] = Base64EncMap[(data[sidx+2] >> 6) & 003 |
+ (data[sidx+1] << 2) & 077];
+ out[didx++] = Base64EncMap[data[sidx+2] & 077];
+ sidx += 3;
+ }
+ }
+
+ if (sidx < len)
+ {
+ if ( insertLFs && (count > 0) && (count%76) == 0 )
+ out[didx++] = '\n';
+
+ out[didx++] = Base64EncMap[(data[sidx] >> 2) & 077];
+ if (sidx < len-1)
+ {
+ out[didx++] = Base64EncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out[didx++] = Base64EncMap[(data[sidx+1] << 2) & 077];
+ }
+ else
+ {
+ out[didx++] = Base64EncMap[(data[sidx] << 4) & 077];
+ }
+ }
+
+ // Add padding
+ while (didx < out.size())
+ {
+ out[didx] = '=';
+ didx++;
+ }
+}
+
+SHA1::SHA1() {
+ _hashlen = 160;
+ _init = false;
+ reset();
+}
+
+
+int SHA1::reset() {
+ _h0 = 0x67452301;
+ _h1 = 0xefcdab89;
+ _h2 = 0x98badcfe;
+ _h3 = 0x10325476;
+ _h4 = 0xc3d2e1f0;
+ _nblocks = 0;
+ _count = 0;
+ memset(_buf, 0, 56); // clear the buffer
+
+ _init = true;
+ return 0;
+}
+
+
+int SHA1::size() const {
+ return _hashlen;
+}
+
+
+SHA1::~SHA1() {
+
+}
+
+
+void SHA1::transform(void *data) {
+ unsigned int a, b, c, d, e, tm;
+ unsigned int x[16];
+ unsigned char *_data = (unsigned char *)data;
+
+ a = _h0;
+ b = _h1;
+ c = _h2;
+ d = _h3;
+ e = _h4;
+
+#ifdef WORDS_BIGENDIAN
+ memcpy(x, _data, 64);
+#else
+ int i;
+ unsigned char *p2;
+ for (i = 0, p2 = (unsigned char *)x;
+ i < 16; i++, p2 += 4) {
+ p2[3] = *_data++;
+ p2[2] = *_data++;
+ p2[1] = *_data++;
+ p2[0] = *_data++;
+ }
+#endif
+
+ R(a, b, c, d, e, F1, K1, x[ 0]);
+ R(e, a, b, c, d, F1, K1, x[ 1]);
+ R(d, e, a, b, c, F1, K1, x[ 2]);
+ R(c, d, e, a, b, F1, K1, x[ 3]);
+ R(b, c, d, e, a, F1, K1, x[ 4]);
+ R(a, b, c, d, e, F1, K1, x[ 5]);
+ R(e, a, b, c, d, F1, K1, x[ 6]);
+ R(d, e, a, b, c, F1, K1, x[ 7]);
+ R(c, d, e, a, b, F1, K1, x[ 8]);
+ R(b, c, d, e, a, F1, K1, x[ 9]);
+ R(a, b, c, d, e, F1, K1, x[10]);
+ R(e, a, b, c, d, F1, K1, x[11]);
+ R(d, e, a, b, c, F1, K1, x[12]);
+ R(c, d, e, a, b, F1, K1, x[13]);
+ R(b, c, d, e, a, F1, K1, x[14]);
+ R(a, b, c, d, e, F1, K1, x[15]);
+ R(e, a, b, c, d, F1, K1, M(16));
+ R(d, e, a, b, c, F1, K1, M(17));
+ R(c, d, e, a, b, F1, K1, M(18));
+ R(b, c, d, e, a, F1, K1, M(19));
+ R(a, b, c, d, e, F2, K2, M(20));
+ R(e, a, b, c, d, F2, K2, M(21));
+ R(d, e, a, b, c, F2, K2, M(22));
+ R(c, d, e, a, b, F2, K2, M(23));
+ R(b, c, d, e, a, F2, K2, M(24));
+ R(a, b, c, d, e, F2, K2, M(25));
+ R(e, a, b, c, d, F2, K2, M(26));
+ R(d, e, a, b, c, F2, K2, M(27));
+ R(c, d, e, a, b, F2, K2, M(28));
+ R(b, c, d, e, a, F2, K2, M(29));
+ R(a, b, c, d, e, F2, K2, M(30));
+ R(e, a, b, c, d, F2, K2, M(31));
+ R(d, e, a, b, c, F2, K2, M(32));
+ R(c, d, e, a, b, F2, K2, M(33));
+ R(b, c, d, e, a, F2, K2, M(34));
+ R(a, b, c, d, e, F2, K2, M(35));
+ R(e, a, b, c, d, F2, K2, M(36));
+ R(d, e, a, b, c, F2, K2, M(37));
+ R(c, d, e, a, b, F2, K2, M(38));
+ R(b, c, d, e, a, F2, K2, M(39));
+ R(a, b, c, d, e, F3, K3, M(40));
+ R(e, a, b, c, d, F3, K3, M(41));
+ R(d, e, a, b, c, F3, K3, M(42));
+ R(c, d, e, a, b, F3, K3, M(43));
+ R(b, c, d, e, a, F3, K3, M(44));
+ R(a, b, c, d, e, F3, K3, M(45));
+ R(e, a, b, c, d, F3, K3, M(46));
+ R(d, e, a, b, c, F3, K3, M(47));
+ R(c, d, e, a, b, F3, K3, M(48));
+ R(b, c, d, e, a, F3, K3, M(49));
+ R(a, b, c, d, e, F3, K3, M(50));
+ R(e, a, b, c, d, F3, K3, M(51));
+ R(d, e, a, b, c, F3, K3, M(52));
+ R(c, d, e, a, b, F3, K3, M(53));
+ R(b, c, d, e, a, F3, K3, M(54));
+ R(a, b, c, d, e, F3, K3, M(55));
+ R(e, a, b, c, d, F3, K3, M(56));
+ R(d, e, a, b, c, F3, K3, M(57));
+ R(c, d, e, a, b, F3, K3, M(58));
+ R(b, c, d, e, a, F3, K3, M(59));
+ R(a, b, c, d, e, F4, K4, M(60));
+ R(e, a, b, c, d, F4, K4, M(61));
+ R(d, e, a, b, c, F4, K4, M(62));
+ R(c, d, e, a, b, F4, K4, M(63));
+ R(b, c, d, e, a, F4, K4, M(64));
+ R(a, b, c, d, e, F4, K4, M(65));
+ R(e, a, b, c, d, F4, K4, M(66));
+ R(d, e, a, b, c, F4, K4, M(67));
+ R(c, d, e, a, b, F4, K4, M(68));
+ R(b, c, d, e, a, F4, K4, M(69));
+ R(a, b, c, d, e, F4, K4, M(70));
+ R(e, a, b, c, d, F4, K4, M(71));
+ R(d, e, a, b, c, F4, K4, M(72));
+ R(c, d, e, a, b, F4, K4, M(73));
+ R(b, c, d, e, a, F4, K4, M(74));
+ R(a, b, c, d, e, F4, K4, M(75));
+ R(e, a, b, c, d, F4, K4, M(76));
+ R(d, e, a, b, c, F4, K4, M(77));
+ R(c, d, e, a, b, F4, K4, M(78));
+ R(b, c, d, e, a, F4, K4, M(79));
+
+ _h0 += a;
+ _h1 += b;
+ _h2 += c;
+ _h3 += d;
+ _h4 += e;
+
+}
+
+
+bool SHA1::readyToGo() const {
+ return _init;
+}
+
+
+int SHA1::process(const void *block, int len) {
+ if (!_init) {
+ return -1;
+ }
+
+ unsigned char *_block = (unsigned char *)block;
+
+ int cnt = 0;
+ // Flush the buffer before proceeding
+ if (_count == 64) {
+ transform(_buf);
+ _count = 0;
+ _nblocks++;
+ }
+
+ if (!_block) {
+ return 0;
+ }
+
+ if (_count) {
+ for (; len && _count < 64; len--, cnt++) {
+ _buf[_count++] = *_block++;
+ }
+ process(0, 0); // flush the buffer if necessary
+ if (!len) {
+ return cnt;
+ }
+ }
+
+ while (len >= 64) {
+ transform(_block);
+ _count = 0;
+ _nblocks++;
+ len -= 64;
+ cnt += 64;
+ _block += 64;
+ }
+
+ for (; len && _count < 64; len--, cnt++) {
+ _buf[_count++] = *_block++;
+ }
+
+ return cnt;
+}
+
+
+const unsigned char *SHA1::hash() {
+ unsigned int t, msb, lsb;
+ unsigned char *p;
+
+
+ if (!_init) {
+ return (unsigned char *)_buf;
+ }
+
+ process(0, 0);
+
+ msb = 0;
+ t = _nblocks;
+
+ if ((lsb = t << 6) < t) {
+ msb++;
+ }
+
+ msb += t >> 26;
+ t = lsb;
+
+ if ((lsb = t + _count) < t) {
+ msb++;
+ }
+
+ t = lsb;
+
+ if ((lsb = t << 3) < t) {
+ msb++;
+ }
+
+ msb += t >> 29;
+
+ _buf[_count++] = 0x80;
+
+ if (_count < 56) {
+ while (_count < 56) {
+ _buf[_count++] = 0;
+ }
+ } else {
+ while (_count < 64) {
+ _buf[_count++] = 0;
+ }
+ process(0, 0);
+ memset(_buf, 0, 56);
+ }
+
+ _buf[56] = msb >> 24;
+ _buf[57] = msb >> 16;
+ _buf[58] = msb >> 8;
+ _buf[59] = msb;
+ _buf[60] = lsb >> 24;
+ _buf[61] = lsb >> 16;
+ _buf[62] = lsb >> 8;
+ _buf[63] = lsb;
+
+ transform(_buf);
+
+ p = _buf;
+
+#ifdef WORDS_BIGENDIAN
+#define X( a ) do { *( uint32_t * )p = _h##a; p += 4; } while ( 0 )
+#else
+#define X(a) do { *p++ = _h##a >> 24; *p++ = _h##a >> 16; \
+ *p++ = _h##a >> 8; *p++ = _h##a; } while (0)
+#endif
+
+ X(0);
+ X(1);
+ X(2);
+ X(3);
+ X(4);
+
+#undef X
+
+ _init = false;
+
+ return (unsigned char *)_buf;
+}
+
+TQString SHA1::base64Hash()
+{
+ const char * output = (const char *)hash();
+ TQByteArray binhash(20);
+ TQByteArray enchash(28);
+ memcpy(binhash.data(), output, 20);
+ base64Encode(binhash, enchash, false);
+ return TQString(enchash);
+}
+
diff --git a/src/sha1.h b/src/sha1.h
new file mode 100644
index 0000000..0341827
--- /dev/null
+++ b/src/sha1.h
@@ -0,0 +1,74 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 George Staikos <staikos@kde.org>
+ Based heavily on SHA1 code from GPG 1.0.3 (C) 1998 FSF
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef __sha1__ko__h
+#define __sha1__ko__h
+
+#include <tqstring.h>
+
+/* @internal
+ */
+class SHA1 {
+ public:
+ SHA1();
+ virtual ~SHA1();
+
+ /*
+ * The number of bits in the hash generated.
+ */
+ virtual int size() const;
+
+ /*
+ * True if all settings are good and we are ready to hash.
+ */
+ virtual bool readyToGo() const;
+
+ /*
+ * Process a block of data for the hash function.
+ */
+ virtual int process(const void *block, int len);
+
+ /*
+ * Return the digest as a 20 byte array reference.
+ * Calling this makes readyToGo() == false.
+ */
+ virtual const unsigned char *hash();
+
+ TQString base64Hash();
+
+ /*
+ * Reset the digest so a new one can be calculated.
+ */
+ virtual int reset();
+
+ protected:
+ int _hashlen;
+ bool _init;
+
+ long _h0, _h1, _h2, _h3, _h4;
+ long _nblocks;
+ int _count;
+ unsigned char _buf[64];
+ void transform(void *data);
+};
+
+
+#endif