diff --git a/src/Makefile.am b/src/Makefile.am index 5bdf85a..d508a2e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,12 +1,11 @@ - -INCLUDES= $(all_includes) +INCLUDES= $(all_includes) $(KDE_INCLUDES)/tde bin_PROGRAMS = kerberostray kerberostray_SOURCES = main.cpp toplevel.cpp kerberostray_METASOURCES = AUTO -kerberostray_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor +kerberostray_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor -ltdeldap # LIB_KIO needed for KNotifyDialog kerberostray_LDADD = $(LIB_TDEUI) $(LIB_KIO) diff --git a/src/cr22-actionkerberos_expiredtickets.png b/src/cr22-action-kerberos_expiredtickets.png similarity index 100% rename from src/cr22-actionkerberos_expiredtickets.png rename to src/cr22-action-kerberos_expiredtickets.png diff --git a/src/cr22-action-kerberos_someexpiredtickets.png b/src/cr22-action-kerberos_someexpiredtickets.png new file mode 100644 index 0000000..c4c0fe5 Binary files /dev/null and b/src/cr22-action-kerberos_someexpiredtickets.png differ diff --git a/src/toplevel.cpp b/src/toplevel.cpp index d1caa0e..bab925e 100644 --- a/src/toplevel.cpp +++ b/src/toplevel.cpp @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include @@ -49,31 +51,42 @@ #include #include #include +#include #include "toplevel.h" #include "toplevel.moc" -TopLevel::TopLevel() : KSystemTray() +TopLevel::TopLevel() : KSystemTray(), ticketWatch(0) { setBackgroundMode(X11ParentRelative); // what for? KConfig *config = kapp->config(); config->setGroup("Kerberos"); - confAct = new KAction(i18n("&Configure..."), "configure", 0, TQT_TQOBJECT(this), TQT_SLOT(config()), actionCollection(), "configure"); + getNewTGTAct = new KAction(i18n("&Obtain New Ticket Granting Ticket"), "add_user", 0, TQT_TQOBJECT(this), TQT_SLOT(getNewTGT()), actionCollection(), "getnewtgt"); + getNewSTAct = new KAction(i18n("&Obtain New Primary Service Ticket"), "add_user", 0, TQT_TQOBJECT(this), TQT_SLOT(getNewServiceTicket()), actionCollection(), "getnewserviceticket"); + destroyAllAct = new KAction(i18n("&Destroy All Tickets"), "delete_user", 0, TQT_TQOBJECT(this), TQT_SLOT(destroyAllTickets()), actionCollection(), "destroyall"); +// confAct = new KAction(i18n("&Configure..."), "configure", 0, TQT_TQOBJECT(this), TQT_SLOT(config()), actionCollection(), "configure"); // create app menu (displayed on right-click) menu = new TQPopupMenu(); - menu->setCheckable(true); - connect(menu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(teaSelected(int))); + connect(menu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(menuAction(int))); KHelpMenu* help = new KHelpMenu(this, KGlobal::instance()->aboutData(), false); KPopupMenu* helpMnu = help->menu(); menu->insertSeparator(); - confAct->plug(menu); + getNewTGTAct->plug(menu); + getNewSTAct->plug(menu); + destroyAllAct->plug(menu); + menu->insertSeparator(); +// confAct->plug(menu); menu->insertItem(SmallIcon("help"), i18n("&Help"), helpMnu); menu->insertItem(SmallIcon("exit"), i18n("Quit"), kapp, TQT_SLOT(quit())); + + // RAJA FIXME + // Should be on a timer or something + updateTicketList(); } /* slot: signal shutDown() from KApplication */ @@ -89,25 +102,130 @@ void TopLevel::queryExit() /** Destructor */ TopLevel::~TopLevel() { + if (ticketWatch) delete ticketWatch; + delete menu; // FIXME: must delete more (like all the TQWidgets in config-window)? } +void TopLevel::updateTicketList() { + m_ticketList = LDAPManager::getKerberosTicketList(TQString::null, &m_ticketFile); + + m_ticketFile.replace("FILE:", ""); +printf("[RAJA DEBUG 980.0] Got ticket cache %s\n\r", m_ticketFile.ascii()); fflush(stdout); + + if (!ticketWatch) { + ticketWatch = new KDirWatch(); + connect(ticketWatch, TQT_SIGNAL(dirty(const TQString&)), this, TQT_SLOT(updateTicketList())); + connect(ticketWatch, TQT_SIGNAL(created(const TQString&)), this, TQT_SLOT(updateTicketList())); + connect(ticketWatch, TQT_SIGNAL(deleted(const TQString&)), this, TQT_SLOT(updateTicketList())); + ticketWatch->addFile(m_ticketFile); + ticketWatch->startScan(); + } + else { + ticketWatch->removeFile(m_ticketFile); + ticketWatch->addFile(m_ticketFile); + ticketWatch->startScan(); + } + + // RAJA FIXME + // Find the next ticket expiry and set a timer to refresh just after expiry + // Better yet, how about flashing a warning when tickets are going to expire shortly? + + repaint(); +} + +void TopLevel::updateMenu() { + // First, remove all current ticket entries from the menu; these can be identified by their positive id + while (menu->idAt(0) >= 0) { + menu->removeItemAt(0); + } + + // Add the new ticket entries to the top of the menu + int id = 0; + int index = 0; + if (m_ticketList.count() < 1) { + menu->insertItem(i18n("No Kerberos Tickets Available"), id++, index++); + menu->setItemEnabled(0, false); + } + else { + KerberosTicketInfoList::Iterator it; + for (it = m_ticketList.begin(); it != m_ticketList.end(); ++it) { + KerberosTicketInfo ticket = *it; + TQDateTime now = TQDateTime::currentDateTime(); + + TQString label = ticket.serverPrincipal; + if (ticket.validEndTime > now) { + label = label + i18n("(Active)"); + } + else { + label = label + i18n("(Expired)"); + } + menu->insertItem(label, id++, index++); + } + } +} + +void TopLevel::getNewTicket(bool requestServiceTicket) { + // RAJA FIXME + LDAPCredentials credentials; + if (m_ticketList.count() > 0) { + TQStringList princParts = TQStringList::split("@", m_ticketList[0].cachePrincipal); + credentials.username = princParts[0]; + credentials.realm = princParts[1]; + } + else { + struct passwd* pwd = getpwuid(geteuid()); + if (pwd) { + credentials.username = TQString(pwd->pw_name); + } + } + int result = LDAPManager::getKerberosPassword(credentials, i18n("Please provide Kerberos credentials"), requestServiceTicket, this); + if (result == KDialog::Accepted) { + TQString errorstring; + TQString service; + if (requestServiceTicket) { + service = credentials.service; + } + if (LDAPManager::obtainKerberosTicket(credentials, service, &errorstring) != 0) { + KMessageBox::error(this, i18n("Failed to obtain ticket

%1").arg(errorstring), i18n("Failed to obtain Kerberos ticket")); + } + } + + updateTicketList(); +} + +void TopLevel::getNewTGT() { + getNewTicket(false); +} + +void TopLevel::getNewServiceTicket() { + getNewTicket(true); +} + +void TopLevel::destroyAllTickets() { + if (system("kdestroy --all") != 0) { + KMessageBox::error(this, i18n("Unable to destroy tickets!"), i18n("Internal Error")); + } + updateTicketList(); +} + void TopLevel::resizeEvent ( TQResizeEvent * ) { activeTicketsPixmap = loadSizedIcon("kerberos_activetickets", width()); noTicketsPixmap = loadSizedIcon("kerberos_notickets", width()); expiredTicketsPixmap = loadSizedIcon("kerberos_expiredtickets", width()); + partiallyExpiredTicketsPixmap = loadSizedIcon("kerberos_someexpiredtickets", width()); repaint(); } /** Handle mousePressEvent */ -void TopLevel::mousePressEvent(TQMouseEvent *event) -{ +void TopLevel::mousePressEvent(TQMouseEvent *event) { if (event->button() == Qt::LeftButton) { - // + showTicketList(); } else if (event->button() == Qt::RightButton) { + updateMenu(); menu->popup(TQCursor::pos()); } else if (event->button() == MidButton) { @@ -116,10 +234,38 @@ void TopLevel::mousePressEvent(TQMouseEvent *event) } /** Handle paintEvent (ie. animate icon) */ -void TopLevel::paintEvent(TQPaintEvent *) -{ +void TopLevel::paintEvent(TQPaintEvent *) { TQPixmap *pm = &noTicketsPixmap; + bool has_tickets = false; + bool some_tickets_expired = false; + bool all_tickets_expired = true; + + KerberosTicketInfoList::Iterator it; + for (it = m_ticketList.begin(); it != m_ticketList.end(); ++it) { + KerberosTicketInfo ticket = *it; + has_tickets = true; + TQDateTime now = TQDateTime::currentDateTime(); + if (ticket.validEndTime > now) { + all_tickets_expired = false; + } + else { + some_tickets_expired = true; + } + } + + if (has_tickets) { + if (all_tickets_expired) { + pm = &expiredTicketsPixmap; + } + else if (some_tickets_expired) { + pm = &partiallyExpiredTicketsPixmap; + } + else { + pm = &activeTicketsPixmap; + } + } + // RAJA FIXME TQPixmap base(*pm); // make copy of base pixmap @@ -128,15 +274,12 @@ void TopLevel::paintEvent(TQPaintEvent *) p.end(); } -/** Check timer and initiate appropriate action if finished */ -void TopLevel::timerEvent(TQTimerEvent *) -{ +void TopLevel::timerEvent(TQTimerEvent *) { // } /** update ToolTip */ -void TopLevel::setToolTip(const TQString &text, bool force) -{ +void TopLevel::setToolTip(const TQString &text, bool force) { // don't update if text hasn't changed if (lastTip == text) { return; @@ -151,13 +294,66 @@ void TopLevel::setToolTip(const TQString &text, bool force) } } +TQString addTicketInfo(TQString origString, KerberosTicketInfo ticket) { + origString += i18n("Server: ") + ticket.serverPrincipal + "
"; + origString += i18n("Client: ") + ticket.clientPrincipal + "
"; + origString += i18n("Encryption Type: ") + ticket.encryptionType + "
"; + origString += i18n("Key Version: %1").arg(ticket.keyVersionNumber) + "
"; + if (ticket.authenticationTime.isValid()) origString += i18n("Authenticated: ") + ticket.authenticationTime.toString() + "
"; + if (ticket.validStartTime.isValid()) origString += i18n("Valid After: ") + ticket.validStartTime.toString() + "
"; + if (ticket.validEndTime.isValid()) origString += i18n("Valid Before: ") + ticket.validEndTime.toString() + "
"; + return origString; +} + +void TopLevel::showTicketList() { + int i; + TQString listText = ""; + updateTicketList(); + if (m_ticketList.count() <= 0) { + listText += "No Kerberos tickets to display!"; + } + else { + i = 1; + KerberosTicketInfoList::Iterator it; + for (it = m_ticketList.begin(); it != m_ticketList.end(); ++it) { + KerberosTicketInfo ticket = *it; + + listText += i18n("Kerberos Ticket %1").arg(i) + "
"; + listText += addTicketInfo("", ticket); + + listText += "

"; + i++; + } + } + listText += ""; + + KMessageBox::information(this, listText, i18n("Kerberos Ticket Information"), TQString::null, KMessageBox::Notify); +} + +void TopLevel::menuAction(int index) { + if (index >= 0) { + TQString listText = ""; + KerberosTicketInfo ticket = m_ticketList[index]; + + listText += i18n("Kerberos Ticket %1").arg(index+1) + "
"; + listText += addTicketInfo("", ticket); + + listText += "
"; + + if (KMessageBox::warningYesNo(this, listText, i18n("Kerberos Ticket Information"), TQString("Destroy this Ticket"), TQString("Cancel")) == KMessageBox::Yes) { + TQString errorstring; + if (LDAPManager::destroyKerberosTicket(ticket.serverPrincipal, &errorstring) != 0) { + KMessageBox::error(this, i18n("Failed to destroy ticket
%1

%2").arg(ticket.serverPrincipal).arg(errorstring), i18n("Failed to destroy Kerberos ticket")); + } + } + } +} + /* config-slot: "help" button clicked */ -void TopLevel::help() -{ +void TopLevel::help() { kapp->invokeHelp(); } -void TopLevel::config() -{ +void TopLevel::config() { // } diff --git a/src/toplevel.h b/src/toplevel.h index 37b75ee..c01c2ad 100644 --- a/src/toplevel.h +++ b/src/toplevel.h @@ -32,6 +32,9 @@ #include #include #include +#include + +#include class KAction; class KDialogBase; @@ -59,11 +62,29 @@ private slots: void help(); void setToolTip(const TQString &text, bool force=false); + void updateTicketList(); + void updateMenu(); + void getNewTGT(); + void getNewServiceTicket(); + void getNewTicket(bool requestServiceTicket=false); + void destroyAllTickets(); + void showTicketList(); + void menuAction(int index); + private: - TQPixmap activeTicketsPixmap, noTicketsPixmap, expiredTicketsPixmap; + TQPixmap activeTicketsPixmap; + TQPixmap noTicketsPixmap; + TQPixmap expiredTicketsPixmap; + TQPixmap partiallyExpiredTicketsPixmap; KAction *confAct; + KAction *getNewTGTAct; + KAction *getNewSTAct; + KAction *destroyAllAct; TQPopupMenu *menu; TQString lastTip; + KerberosTicketInfoList m_ticketList; + TQString m_ticketFile; + KDirWatch *ticketWatch; }; #endif