Add a variety of ticket management functions

pull/1/head
Timothy Pearson 13 years ago
parent df417d4eda
commit 072098e10d

@ -68,6 +68,25 @@
</property> </property>
</widget> </widget>
<widget class="TQLabel" row="4" column="0" colspan="2"> <widget class="TQLabel" row="4" column="0" colspan="2">
<property name="name">
<cstring>kerberosOtherInfoString</cstring>
</property>
<property name="text">
<string>Service Principal</string>
</property>
<property name="hidden">
<cstring>true</cstring>
</property>
</widget>
<widget class="KLineEdit" row="4" column="2">
<property name="name">
<cstring>kerberosServicePrincipal</cstring>
</property>
<property name="hidden">
<cstring>true</cstring>
</property>
</widget>
<widget class="TQLabel" row="5" column="0" colspan="2">
<property name="name"> <property name="name">
<cstring>unnamed</cstring> <cstring>unnamed</cstring>
</property> </property>
@ -75,12 +94,12 @@
<string>LDAP Realm</string> <string>LDAP Realm</string>
</property> </property>
</widget> </widget>
<widget class="KComboBox" row="4" column="2"> <widget class="KComboBox" row="5" column="2">
<property name="name"> <property name="name">
<cstring>ldapAdminRealm</cstring> <cstring>ldapAdminRealm</cstring>
</property> </property>
</widget> </widget>
<widget class="TQCheckBox" row="4" column="0" colspan="3"> <widget class="TQCheckBox" row="5" column="0" colspan="3">
<property name="name"> <property name="name">
<cstring>ldapUseTLS</cstring> <cstring>ldapUseTLS</cstring>
</property> </property>

@ -32,8 +32,8 @@
#include "ldaplogindlg.h" #include "ldaplogindlg.h"
#include "ldappasswddlg.h" #include "ldappasswddlg.h"
LDAPPasswordDialog::LDAPPasswordDialog(TQWidget* parent, const char* name) LDAPPasswordDialog::LDAPPasswordDialog(TQWidget* parent, const char* name, bool allowGSSAPI)
: KDialogBase(parent, name, true, i18n("LDAP Authentication"), Ok|Cancel|User1, Ok, true, i18n("Authenticate with SASL/GSSAPI")) : KDialogBase(parent, name, true, i18n("LDAP Authentication"), (allowGSSAPI)?Ok|Cancel|User1:Ok|Cancel, Ok, true, i18n("Authenticate with SASL/GSSAPI"))
{ {
m_base = new LDAPLogin(this); m_base = new LDAPLogin(this);

@ -31,7 +31,7 @@ class LDAPPasswordDialog : public KDialogBase
Q_OBJECT Q_OBJECT
public: public:
LDAPPasswordDialog(TQWidget* parent = 0, const char* name = 0); LDAPPasswordDialog(TQWidget* parent = 0, const char* name = 0, bool allowGSSAPI = true);
public slots: public slots:
void slotOk(); void slotOk();

@ -35,6 +35,7 @@
#include <ksimpleconfig.h> #include <ksimpleconfig.h>
#include <tdesu/process.h> #include <tdesu/process.h>
#include <ksslcertificate.h> #include <ksslcertificate.h>
#include <krfcdate.h>
#include <ldap.h> #include <ldap.h>
#include <stdlib.h> #include <stdlib.h>
@ -153,6 +154,8 @@ printf("[RAJA DEBUG 600.0] In LDAPManager::bind(%p)\n\r", errstr); fflush(stdout
return 0; return 0;
} }
KerberosTicketInfoList m_krbTickets = LDAPManager::getKerberosTicketList();
bool using_ldapi = false; bool using_ldapi = false;
bool using_gssapi = false; bool using_gssapi = false;
if (m_host.startsWith("ldapi://")) { if (m_host.startsWith("ldapi://")) {
@ -164,7 +167,7 @@ printf("[RAJA DEBUG 600.0] In LDAPManager::bind(%p)\n\r", errstr); fflush(stdout
} }
else { else {
printf("[RAJA DEBUG 660.1]\n\r"); fflush(stdout); printf("[RAJA DEBUG 660.1]\n\r"); fflush(stdout);
LDAPPasswordDialog passdlg(0); LDAPPasswordDialog passdlg(0, 0, (m_krbTickets.count() > 0));
passdlg.m_base->ldapAdminRealm->setEnabled(false); passdlg.m_base->ldapAdminRealm->setEnabled(false);
passdlg.m_base->ldapAdminRealm->insertItem(m_realm); passdlg.m_base->ldapAdminRealm->insertItem(m_realm);
passdlg.m_base->ldapUseTLS->setChecked(true); passdlg.m_base->ldapUseTLS->setChecked(true);
@ -865,6 +868,11 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
// RAJA FIXME // RAJA FIXME
// How to handle GSSAPI auth? // How to handle GSSAPI auth?
// We can't really at this point
// GSSAPI and friends ONLY WORK if 'kinit -S kadmin/admin' was run after the inital TGT was granted
// What we need is a proper ticket management system
// Also, why doesn't 'kgetcred kadmin/admin' work?
// For now, let's just prompt for the password if admincreds.password == ""
TQCString command = "kadmin"; TQCString command = "kadmin";
QCStringList args; QCStringList args;
@ -928,6 +936,314 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
return 1; // Failure return 1; // Failure
} }
TQString klistDateTimeToRFCDateTime(TQString datetime) {
// HACK HACK HACK
// FIXME
TQString ret;
TQString command = TQString("date -R -d \"%1\"").arg(datetime);
FILE *output = popen(command.ascii(), "r");
TQFile f;
f.open(IO_ReadOnly, output);
TQTextStream stream(&f);
ret = stream.readLine();
f.close();
pclose(output);
return ret;
}
#define KLIST_CREDENTIALS_CACHE_STRING "Credentials cache: "
#define KLIST_PRINCIPAL_STRING "Principal: "
#define KLIST_CACHE_VERSION_STRING "Cache version: "
#define KLIST_SERVER_STRING "Server: "
#define KLIST_CLIENT_STRING "Client: "
#define KLIST_ENCTYPE_STRING "Ticket etype: "
#define KLIST_TICKET_LENGTH_STRING "Ticket length: "
#define KLIST_AUTHTIME_STRING "Auth time: "
#define KLIST_STARTTIME_STRING "Start time: "
#define KLIST_STOPTIME_STRING "End time: "
#define KLIST_FLAGS_STRING "Ticket flags: "
#define KLIST_ADDRESSES_STRING "Ticket flags: "
#define KLIST_NO_TICKET_FILE "klist: No ticket file: "
#define KLIST_KVNO_STRING "kvno"
#define KLIST_ADDRESSLESS_STRING "addressless"
#define KLIST_KRB5_TICKET_RESERVED "reserved"
#define KLIST_KRB5_TICKET_FORWARDABLE "forwardable"
#define KLIST_KRB5_TICKET_FORWARDED "forwarded"
#define KLIST_KRB5_TICKET_PROXIABLE "proxiable"
#define KLIST_KRB5_TICKET_PROXY "proxy"
#define KLIST_KRB5_TICKET_MAY_POSTDATE "may-postdate"
#define KLIST_KRB5_TICKET_POSTDATED "postdated"
#define KLIST_KRB5_TICKET_INVALID "invalid"
#define KLIST_KRB5_TICKET_RENEWABLE "renewable"
#define KLIST_KRB5_TICKET_INITIAL "initial"
#define KLIST_KRB5_TICKET_PREAUTHENT "pre-authent"
#define KLIST_KRB5_TICKET_HW_AUTHENT "hw-authent"
#define KLIST_KRB5_TICKET_TRANSIT_CHECKED "transited-policy-checked"
#define KLIST_KRB5_TICKET_OK_AS_DELEGATE "ok-as-delegate"
#define KLIST_KRB5_TICKET_ANONYMOUS "anonymous"
#define KLIST_KRB5_TICKET_ENC_PA_REP "enc-pa-rep"
KerberosTicketInfoList LDAPManager::getKerberosTicketList(TQString cache, TQString *cacheFileName) {
KerberosTicketInfo ticket;
KerberosTicketInfoList list;
TQString global_ccache;
TQString global_principal;
TQString global_cachevers;
TQString line;
FILE *output = popen("klist -v 2>&1", "r");
TQFile f;
f.open(IO_ReadOnly, output);
TQTextStream stream(&f);
while ( !stream.atEnd() ) {
line = stream.readLine();
line = line.stripWhiteSpace();
if (line == "") {
if (ticket.informationValid) {
ticket.cacheURL = global_ccache;
ticket.cachePrincipal = global_principal;
ticket.cacheVersion = global_cachevers.toInt();
list.append(ticket);
}
ticket = KerberosTicketInfo();
}
else if (line.startsWith(KLIST_NO_TICKET_FILE)) {
line.remove(0, strlen(KLIST_NO_TICKET_FILE));
line.prepend("FILE:");
if (cacheFileName) *cacheFileName = line;
}
else if (line.startsWith(KLIST_CREDENTIALS_CACHE_STRING)) {
line.remove(0, strlen(KLIST_CREDENTIALS_CACHE_STRING));
global_ccache = line;
if (cacheFileName) *cacheFileName = line;
}
else if (line.startsWith(KLIST_PRINCIPAL_STRING)) {
line.remove(0, strlen(KLIST_PRINCIPAL_STRING));
global_principal = line;
}
else if (line.startsWith(KLIST_CACHE_VERSION_STRING)) {
line.remove(0, strlen(KLIST_CACHE_VERSION_STRING));
global_cachevers = line;
}
else if (line.startsWith(KLIST_SERVER_STRING)) {
line.remove(0, strlen(KLIST_SERVER_STRING));
ticket.serverPrincipal = line;
ticket.informationValid = true;
}
else if (line.startsWith(KLIST_CLIENT_STRING)) {
line.remove(0, strlen(KLIST_CLIENT_STRING));
ticket.clientPrincipal = line;
ticket.informationValid = true;
}
else if (line.startsWith(KLIST_ENCTYPE_STRING)) {
line.remove(0, strlen(KLIST_ENCTYPE_STRING));
TQString kvno = line;
int commaloc = line.find(",");
kvno.remove(0, commaloc+1);
kvno.replace(KLIST_KVNO_STRING, "");
kvno = kvno.stripWhiteSpace();
line.truncate(commaloc);
ticket.encryptionType = line;
ticket.keyVersionNumber = kvno.toInt();
ticket.informationValid = true;
}
else if (line.startsWith(KLIST_TICKET_LENGTH_STRING)) {
line.remove(0, strlen(KLIST_TICKET_LENGTH_STRING));
ticket.ticketSize = line.toInt();
ticket.informationValid = true;
}
else if (line.startsWith(KLIST_AUTHTIME_STRING)) {
line.remove(0, strlen(KLIST_AUTHTIME_STRING));
line.replace("(expired)", "");
line = line.simplifyWhiteSpace();
line = klistDateTimeToRFCDateTime(line);
ticket.authenticationTime.setTime_t(KRFCDate::parseDate(line));
ticket.informationValid = true;
}
else if (line.startsWith(KLIST_STARTTIME_STRING)) {
line.remove(0, strlen(KLIST_STARTTIME_STRING));
line.replace("(expired)", "");
line = line.simplifyWhiteSpace();
line = klistDateTimeToRFCDateTime(line);
ticket.validStartTime.setTime_t(KRFCDate::parseDate(line));
ticket.informationValid = true;
}
else if (line.startsWith(KLIST_STOPTIME_STRING)) {
line.remove(0, strlen(KLIST_STOPTIME_STRING));
line.replace("(expired)", "");
line = line.simplifyWhiteSpace();
line = klistDateTimeToRFCDateTime(line);
ticket.validEndTime.setTime_t(KRFCDate::parseDate(line));
ticket.informationValid = true;
}
else if (line.startsWith(KLIST_FLAGS_STRING)) {
line.remove(0, strlen(KLIST_FLAGS_STRING));
TQStringList flags = TQStringList::split(",", line, FALSE);
for (TQStringList::Iterator it = flags.begin(); it != flags.end(); ++it) {
if ((*it) == KLIST_KRB5_TICKET_RESERVED) {
ticket.flags = ticket.flags | KRB5_TICKET_RESERVED;
}
else if ((*it) == KLIST_KRB5_TICKET_FORWARDABLE) {
ticket.flags = ticket.flags | KRB5_TICKET_FORWARDABLE;
}
else if ((*it) == KLIST_KRB5_TICKET_FORWARDED) {
ticket.flags = ticket.flags | KRB5_TICKET_FORWARDED;
}
else if ((*it) == KLIST_KRB5_TICKET_PROXIABLE) {
ticket.flags = ticket.flags | KRB5_TICKET_PROXIABLE;
}
else if ((*it) == KLIST_KRB5_TICKET_PROXY) {
ticket.flags = ticket.flags | KRB5_TICKET_PROXY;
}
else if ((*it) == KLIST_KRB5_TICKET_MAY_POSTDATE) {
ticket.flags = ticket.flags | KRB5_TICKET_MAY_POSTDATE;
}
else if ((*it) == KLIST_KRB5_TICKET_POSTDATED) {
ticket.flags = ticket.flags | KRB5_TICKET_POSTDATED;
}
else if ((*it) == KLIST_KRB5_TICKET_INVALID) {
ticket.flags = ticket.flags | KRB5_TICKET_INVALID;
}
else if ((*it) == KLIST_KRB5_TICKET_RENEWABLE) {
ticket.flags = ticket.flags | KRB5_TICKET_RENEWABLE;
}
else if ((*it) == KLIST_KRB5_TICKET_INITIAL) {
ticket.flags = ticket.flags | KRB5_TICKET_INITIAL;
}
else if ((*it) == KLIST_KRB5_TICKET_PREAUTHENT) {
ticket.flags = ticket.flags | KRB5_TICKET_PREAUTHENT;
}
else if ((*it) == KLIST_KRB5_TICKET_HW_AUTHENT) {
ticket.flags = ticket.flags | KRB5_TICKET_HW_AUTHENT;
}
else if ((*it) == KLIST_KRB5_TICKET_TRANSIT_CHECKED) {
ticket.flags = ticket.flags | KRB5_TICKET_TRANSIT_CHECKED;
}
else if ((*it) == KLIST_KRB5_TICKET_OK_AS_DELEGATE) {
ticket.flags = ticket.flags | KRB5_TICKET_OK_AS_DELEGATE;
}
else if ((*it) == KLIST_KRB5_TICKET_ANONYMOUS) {
ticket.flags = ticket.flags | KRB5_TICKET_ANONYMOUS;
}
else if ((*it) == KLIST_KRB5_TICKET_ENC_PA_REP) {
ticket.flags = ticket.flags | KRB5_TICKET_ENC_PA_REP;
}
}
ticket.informationValid = true;
}
else if (line.startsWith(KLIST_ADDRESSES_STRING)) {
line.remove(0, strlen(KLIST_ADDRESSES_STRING));
if (line != KLIST_ADDRESSLESS_STRING) {
// FIXME
// What is the separator?
ticket.addresses = TQStringList(line);
}
ticket.informationValid = true;
}
}
f.close();
pclose(output);
return list;
}
int LDAPManager::getKerberosPassword(LDAPCredentials &creds, TQString prompt, bool requestServicePrincipal, TQWidget* parent)
{
int i;
KSimpleConfig* systemconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/ldap/ldapconfigrc" ));
systemconfig->setGroup(NULL);
TQString defaultRealm = systemconfig->readEntry("DefaultRealm", TQString::null);
LDAPRealmConfigList realms = LDAPManager::readTDERealmList(systemconfig, false);
delete systemconfig;
if (creds.realm != "") {
defaultRealm = creds.realm;
}
LDAPPasswordDialog passdlg(parent, 0, false);
passdlg.m_base->ldapAdminRealm->setEnabled(true);
LDAPRealmConfigList::Iterator it;
i=0;
for (it = realms.begin(); it != realms.end(); ++it) {
passdlg.m_base->ldapAdminRealm->insertItem((*it).name);
if ((*it).name == defaultRealm) {
passdlg.m_base->ldapAdminRealm->setCurrentItem(i);
}
i++;
}
passdlg.m_base->passprompt->setText(prompt);
passdlg.m_base->ldapUseTLS->hide();
if (requestServicePrincipal) {
passdlg.m_base->kerberosOtherInfoString->show();
passdlg.m_base->kerberosServicePrincipal->show();
}
if (creds.username != "") {
passdlg.m_base->ldapAdminUsername->setText(creds.username);
passdlg.m_base->ldapAdminPassword->setFocus();
}
const int ret = passdlg.exec();
if (ret == KDialog::Accepted) {
creds.username = passdlg.m_base->ldapAdminUsername->text();
creds.password = passdlg.m_base->ldapAdminPassword->password();
creds.realm = passdlg.m_base->ldapAdminRealm->currentText();
creds.service = passdlg.m_base->kerberosServicePrincipal->text();
creds.use_tls = passdlg.m_base->ldapUseTLS->isOn();
}
return ret;
}
int LDAPManager::obtainKerberosTicket(LDAPCredentials creds, TQString principal, TQString *errstr) {
TQCString command = "kinit";
QCStringList args;
if (principal == "") {
args << TQCString(creds.username + "@" + creds.realm.upper());
}
else {
args << TQCString("-S") << TQCString(principal) << TQCString(creds.username + "@" + creds.realm.upper());
}
TQString prompt;
PtyProcess kadminProc;
kadminProc.exec(command, args);
prompt = kadminProc.readLine(true);
prompt = prompt.stripWhiteSpace();
if (prompt.endsWith(" Password:")) {
kadminProc.writeLine(creds.password, true);
prompt = kadminProc.readLine(true); // Discard our own input
prompt = kadminProc.readLine(true);
prompt = prompt.stripWhiteSpace();
}
if (prompt != "") {
if (errstr) *errstr = prompt;
return 1;
}
// Success!
return 0;
}
int LDAPManager::destroyKerberosTicket(TQString principal, TQString *errstr) {
TQString ret;
TQString command = TQString("kdestroy --credential=\"%1\"").arg(principal);
FILE *output = popen(command.ascii(), "r");
TQFile f;
f.open(IO_ReadOnly, output);
TQTextStream stream(&f);
ret = stream.readLine();
f.close();
pclose(output);
if (ret != "") {
if (errstr) *errstr = ret;
return -1;
}
return 0;
}
int LDAPManager::updateGroupInfo(LDAPGroupInfo group) { int LDAPManager::updateGroupInfo(LDAPGroupInfo group) {
int retcode; int retcode;
int i; int i;
@ -1992,4 +2308,18 @@ LDAPTDEBuiltinsInfo::~LDAPTDEBuiltinsInfo() {
// //
} }
KerberosTicketInfo::KerberosTicketInfo() {
// TQStrings are always initialized to TQString::null, so they don't need initialization here...
informationValid = false;
cacheVersion = -1;
keyVersionNumber = -1;
ticketSize = -1;
flags = (KRB5TicketFlags)0;
}
KerberosTicketInfo::~KerberosTicketInfo() {
//
}
#include "libtdeldap.moc" #include "libtdeldap.moc"

@ -77,6 +77,48 @@ enum LDAPKRB5Flags {
KRB5_FLAG_MAX = 0x80000000 KRB5_FLAG_MAX = 0x80000000
}; };
inline LDAPKRB5Flags operator|(LDAPKRB5Flags a, LDAPKRB5Flags b)
{
return static_cast<LDAPKRB5Flags>(static_cast<int>(a) | static_cast<int>(b));
}
inline LDAPKRB5Flags operator&(LDAPKRB5Flags a, LDAPKRB5Flags b)
{
return static_cast<LDAPKRB5Flags>(static_cast<int>(a) & static_cast<int>(b));
}
// Values from krb5.asn1
enum KRB5TicketFlags {
KRB5_TICKET_RESERVED = 0x00000001,
KRB5_TICKET_FORWARDABLE = 0x00000002,
KRB5_TICKET_FORWARDED = 0x00000004,
KRB5_TICKET_PROXIABLE = 0x00000008,
KRB5_TICKET_PROXY = 0x00000010,
KRB5_TICKET_MAY_POSTDATE = 0x00000020,
KRB5_TICKET_POSTDATED = 0x00000040,
KRB5_TICKET_INVALID = 0x00000080,
KRB5_TICKET_RENEWABLE = 0x00000100,
KRB5_TICKET_INITIAL = 0x00000200,
KRB5_TICKET_PREAUTHENT = 0x00000400,
KRB5_TICKET_HW_AUTHENT = 0x00000800,
KRB5_TICKET_TRANSIT_CHECKED = 0x00001000,
KRB5_TICKET_OK_AS_DELEGATE = 0x00002000,
KRB5_TICKET_ANONYMOUS = 0x00004000,
KRB5_TICKET_ENC_PA_REP = 0x00008000,
KRB5_TICKET_FLAG_MAX = 0x80000000
};
inline KRB5TicketFlags operator|(KRB5TicketFlags a, KRB5TicketFlags b)
{
return static_cast<KRB5TicketFlags>(static_cast<int>(a) | static_cast<int>(b));
}
inline KRB5TicketFlags operator&(KRB5TicketFlags a, KRB5TicketFlags b)
{
return static_cast<KRB5TicketFlags>(static_cast<int>(a) & static_cast<int>(b));
}
typedef TQValueList<uid_t> UserList; typedef TQValueList<uid_t> UserList;
typedef TQValueList<gid_t> GroupList; typedef TQValueList<gid_t> GroupList;
@ -91,6 +133,7 @@ class LDAPCredentials
TQCString password; TQCString password;
TQString realm; TQString realm;
bool use_tls; bool use_tls;
TQString service;
}; };
// PRIVATE // PRIVATE
@ -262,9 +305,33 @@ class LDAPTDEBuiltinsInfo
TQString builtinStandardUserGroup; TQString builtinStandardUserGroup;
}; };
class KerberosTicketInfo
{
public:
KerberosTicketInfo();
~KerberosTicketInfo();
public:
bool informationValid;
TQString cacheURL;
TQString cachePrincipal;
int cacheVersion;
TQString serverPrincipal;
TQString clientPrincipal;
TQString encryptionType;
int keyVersionNumber;
int ticketSize;
TQDateTime authenticationTime;
TQDateTime validStartTime;
TQDateTime validEndTime;
KRB5TicketFlags flags;
TQStringList addresses;
};
typedef TQValueList<LDAPUserInfo> LDAPUserInfoList; typedef TQValueList<LDAPUserInfo> LDAPUserInfoList;
typedef TQValueList<LDAPGroupInfo> LDAPGroupInfoList; typedef TQValueList<LDAPGroupInfo> LDAPGroupInfoList;
typedef TQValueList<LDAPMachineInfo> LDAPMachineInfoList; typedef TQValueList<LDAPMachineInfo> LDAPMachineInfoList;
typedef TQValueList<KerberosTicketInfo> KerberosTicketInfoList;
class LDAPManager : public TQObject { class LDAPManager : public TQObject {
Q_OBJECT Q_OBJECT
@ -315,6 +382,11 @@ class LDAPManager : public TQObject {
static TQString ldapdnForRealm(TQString realm); static TQString ldapdnForRealm(TQString realm);
static TQString cnFromDn(TQString dn); static TQString cnFromDn(TQString dn);
static KerberosTicketInfoList getKerberosTicketList(TQString cache=TQString::null, TQString *cacheFileName=0);
static int getKerberosPassword(LDAPCredentials &creds, TQString prompt, bool requestServicePrincipal=false, TQWidget* parent=0);
static int obtainKerberosTicket(LDAPCredentials creds, TQString principal, TQString *errstr=0);
static int destroyKerberosTicket(TQString principal, TQString *errstr=0);
private: private:
LDAPUserInfo parseLDAPUserRecord(LDAPMessage* entry); LDAPUserInfo parseLDAPUserRecord(LDAPMessage* entry);
LDAPGroupInfo parseLDAPGroupRecord(LDAPMessage* entry); LDAPGroupInfo parseLDAPGroupRecord(LDAPMessage* entry);

Loading…
Cancel
Save