diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/ldapcontroller.cpp | 195 | ||||
-rw-r--r-- | src/ldapcontroller.h | 13 | ||||
-rw-r--r-- | src/realmfinishpage.cpp | 5 | ||||
-rw-r--r-- | src/realmfinishpagedlg.ui | 17 | ||||
-rw-r--r-- | src/realmwizard.cpp | 3 | ||||
-rw-r--r-- | src/sha1.cc | 433 | ||||
-rw-r--r-- | src/sha1.h | 74 |
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 |