This is Kauth.m in view mode; [Download] [Up]
/* GUI to Kerberos kinit/klist/kdestroy.
*/
#import <defaults.h>
#import <appkit/Panel.h>
#import <appkit/TextField.h>
#import "Subprocess.h"
#import "Reporter.h"
#import "Kauth.h"
int strlen(char *s);
char *strcpy(char *s1, char *s2);
int strcmp(char *s1, char *s2);
char *malloc(unsigned u);
char *realloc(char *b, unsigned u);
void free(char *b);
int system(char *cmd);
char *getname(int uid);
int getuid();
/* Return last nonempty line of a buffer---usually an error message.
*/
char *lastLineOf(buf)
char *buf;
{
char *ep;
if (!buf || !strlen(buf)) {
return "";
} else {
ep= buf+strlen(buf)-1;
if (ep!=buf && *ep=='\n') ep--;
while (ep>buf && *ep!='\n') ep--;
if (*ep=='\n') ep++;
return ep;
}
}
/* Decide if buffer ends with given string. */
int bufferEndsWith(buf, pat)
char *buf;
char *pat;
{
int bl, pl;
if (!buf || !pat) return 0;
bl= strlen(buf); pl= strlen(pat);
if (bl < pl) return 0;
return !strcmp(buf+bl-pl, pat);
}
/* ====================================================================== */
@implementation Kauth
/* ---------------------------------------------------------------------- */
/* Put up the Authenticate panel and start a kinit process */
- showAuthenticate:sender
{
outputBuffer= NULL;
if (!kinitProcess) {
kinitProcess= [Subprocess new];
}
[kinitProcess init:"/usr/local/bin/kinit -r" withDelegate:self
andPtySupport:YES andStdErr:YES];
kinitStage= STARTED;
[principalTextField selectText:sender];
[passwordTextField setStringValue:""];
[authenticateButton setEnabled:NO]; /* enable when kinit prompts */
[authenticatePanel makeKeyAndOrderFront:sender];
return self;
}
/* ---------------------------------------------------------------------- */
/* Send authentication information to the kinit process */
- authenticate:sender
{
if (kinitStage==GOTNAME) {
[kinitProcess send:[principalTextField stringValue]];
kinitStage=SENTNAME;
} else {
printf("Authenticate button enabled at strange time\n");
}
[authenticateButton setEnabled:NO]; /* enable when kinit prompts */
return self;
}
/* ---------------------------------------------------------------------- */
/* Put up the Info panel, with output from klist in it */
- showInfo:sender
{
[klistReporter refresh:sender];
[infoPanel makeKeyAndOrderFront:sender];
return self;
}
/* ====================================================================== */
/* Subprocess Delegation */
/* ---------------------------------------------------------------------- */
/* Deal with output from kinit process: recognize the banner and prompts,
* updating the display and responding to kinit as needed.
*/
-subprocessOutput:(char *)buffer
{
if (outputBuffer) {
outputBuffer=
realloc(outputBuffer,strlen(outputBuffer)+strlen(buffer)+2);
} else {
outputBuffer= malloc(strlen(buffer)+1);
outputBuffer[0]= '\0';
}
strcpy(outputBuffer+strlen(outputBuffer), buffer);
/* deal with banner and prompts, in a state machine */
switch (kinitStage) {
case STARTED: /* waiting for banner and name prompt */
if (bufferEndsWith(outputBuffer,"Kerberos name: ")) {
[kinitBannerTextField setStringValue:outputBuffer];
free(outputBuffer); outputBuffer= NULL;
[authenticateButton setEnabled:YES];
kinitStage= GOTNAME;
}
break;
/* the authenticate method will set kinitStage= SENTNAME */
case SENTNAME: /* waiting for realm prompt */
if (bufferEndsWith(outputBuffer,"Kerberos realm: ")) {
free(outputBuffer); outputBuffer= NULL;
[kinitProcess send:[realmTextField stringValue]];
kinitStage= SENTREALM;
}
break;
case SENTREALM: /* waiting for password prompt */
if (bufferEndsWith(outputBuffer,"Password: ")) {
free(outputBuffer); outputBuffer= NULL;
[kinitProcess send:[passwordTextField stringValue]];
[passwordTextField setStringValue:""];
kinitStage= SENTPASSWD;
}
break;
case SENTPASSWD:
/* got an error message: deal with it in subprocessDone */
break;
default:
printf("Kauth: strange value of kinitStage (%d)\n", kinitStage);
break;
}
return self;
}
/* ---------------------------------------------------------------------- */
/* Deal with end of kinit process: decide what happened.
* Close the Authenticate panel if all is well.
* Otherwise, put up an error message.
*/
- subprocessDone
{
[passwordTextField setStringValue:""];
[klistReporter refresh:self];
if (kinitStage==STARTED) {
NXRunAlertPanel(0,
"Problem starting kinit. Is Kerberos installed?", 0, 0, 0);
[authenticatePanel performClose:self];
} else if (outputBuffer && strlen(outputBuffer)>2) {
NXRunAlertPanel(0, lastLineOf(outputBuffer), 0, 0, 0);
/* restart so that Authenticate button will become re-enabled */
[self showAuthenticate:self];
} else if (kinitStage==SENTPASSWD) {
[authenticatePanel performClose:self]; /* successful */
} else {
NXRunAlertPanel(0, "Kinit started, but then died.", 0, 0, 0);
[self showAuthenticate:self];
}
return self;
}
/* ---------------------------------------------------------------------- */
/* Deal with error form subprocess: put up a panel to tell the user */
- subprocessError:(const char *)errorString
{
[passwordTextField setStringValue:""];
NXRunAlertPanel(0, errorString, 0, 0, 0);
return self;
}
/* ---------------------------------------------------------------------- */
/* Save Principal and Realm to defaults database */
- saveDefaults:sender
{
NXWriteDefault("kerberos", "principal", [principalTextField stringValue]);
NXWriteDefault("kerberos", "realm", [realmTextField stringValue]);
return self;
}
/* ====================================================================== */
/* Application Object Delegation */
- appDidInit:sender
{
const NXDefaultsVector kerberosDefaults = {
{ "principal", "nobody" },
{ "realm", "NOWHERE" },
{ NULL, NULL}
};
NXRegisterDefaults("kerberos", kerberosDefaults);
[klistReporter setCommand:"/usr/local/bin/klist"];
[principalTextField
setStringValue:NXGetDefaultValue("kerberos", "principal")];
[realmTextField setStringValue:NXGetDefaultValue("kerberos", "realm")];
/* [principalTextField setStringValue:getname(getuid())]; */
[self showAuthenticate:sender];
return self;
}
- appWillTerminate:sender
{
/* [self destroyTickets:sender]; */
(void) system("/usr/local/bin/kdestroy"); /* low-tech but reliable */
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.