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.