12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $TOG: Main.c /main/18 1998/07/23 17:56:36 mgreess $ */
- /*****************************************************************************
- *****************************************************************************
- **
- ** File: Main.c
- **
- ** Project: DT
- **
- ** Description: This file contains the main program for dtaction.
- **
- **
- **(c) Copyright 1993, 1994 Hewlett-Packard Company
- **(c) Copyright 1993, 1994 International Business Machines Corp.
- **(c) Copyright 1993, 1994 Sun Microsystems, Inc.
- **(c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
- **
- **
- ****************************************************************************
- ************************************<+>*************************************/
- #include <stdlib.h>
- #include <limits.h>
- #include <stddef.h>
- #include <unistd.h>
- #include <Dt/MsgCatP.h>
- #include <signal.h>
- #include <locale.h>
- #include <sys/param.h> /* for MAXPATHLEN and MAXHOSTNAMELEN */
- #if defined(sun) || defined(__linux__)
- #include <crypt.h>
- #include <shadow.h>
- #endif
- #include <errno.h>
- #include <grp.h>
- #include <pwd.h>
- #include <X11/Intrinsic.h>
- #include <Xm/XmP.h>
- #include <Xm/Text.h>
- #include <Xm/TextF.h>
- #include <Xm/SelectioB.h>
- #include <Xm/MessageB.h>
- #include <Xm/Protocols.h>
- #include <Xm/MwmUtil.h>
- #include <Dt/Dt.h>
- #include <Dt/DbUtil.h>
- #include <Dt/CmdInv.h>
- #include <Dt/Action.h>
- #include <Dt/EnvControlP.h>
- /******************************************************************************/
- #include <time.h>
- /* Command line options */
- XrmOptionDescRec option_list[] =
- {
- { "-user", "user", XrmoptionSepArg, NULL},
- { "-contextDir", "contextDir", XrmoptionSepArg, NULL},
- { "-execHost", "execHost", XrmoptionSepArg, NULL},
- { "-termOpts", "termOpts", XrmoptionSepArg, NULL},
- };
- typedef struct {
- char * user;
- char * contextDir;
- char * execHost;
- char * termOpts;
- } ApplArgs, *ApplArgsPtr;
- #define LOGIN_STR_LEN 15
- #define STAR ' '
- Widget dlog;
- char *password;
- char *stars;
- int passwordLength = 0;
- Boolean finished = False;
- Boolean rootRequest = False;
- char * toPword = NULL;
- char * rootPword = NULL;
- char * origName = "Unknown";
- int basegid = -1;
- int newuid = -1;
- /* Dtaction resources */
- XtResource resources[] =
- {
- {
- "user", "User", XmRString, sizeof(char *),
- XtOffsetOf(ApplArgs, user), XmRImmediate, (XtPointer) NULL,
- },
- {
- "contextDir", "ContextDir", XmRString, sizeof(char *),
- XtOffsetOf(ApplArgs, contextDir), XmRImmediate, (XtPointer) NULL,
- },
- {
- "execHost", "ExecHost", XmRString, sizeof(char *),
- XtOffsetOf(ApplArgs, execHost), XmRImmediate, (XtPointer) NULL,
- },
- {
- "termOpts", "TermParms", XmRString, sizeof(char *),
- XtOffsetOf(ApplArgs, termOpts), XmRImmediate, (XtPointer) NULL,
- },
- };
- /*
- * macro to get message catalog strings
- */
- #ifndef NO_MESSAGE_CATALOG
- # define _CLIENT_CAT_NAME "dtact"
- extern char *_DtGetMessage(char *filename, int set, int n, char *s);
- # define GETMESSAGE(set, number, string)\
- (_DtGetMessage(_CLIENT_CAT_NAME, set, number, string))
- #else
- # define GETMESSAGE(set, number, string)\
- string
- #endif
- Boolean _DtWmStringsAreEqual(
- char *in_str,
- char *test_str) ;
- void CheckForDone(
- XtPointer clientData,
- XtIntervalId id) ;
- void CheckUserRequest( void ) ;
- void CheckPasswd( void ) ;
- void AddSuLog(
- char *FromName,
- char *ToName,
- char *ChangeType) ;
- void CleanPath(
- char *Path) ;
- void OkCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData) ;
- void ErrOkCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData) ;
- void CancelCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData) ;
- void MapCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData) ;
- void actionStatusCallback (
- DtActionInvocationID id,
- XtPointer client_data,
- DtActionArg *aap,
- int aac,
- DtActionStatus status );
- void GetUserPrompt( void ) ;
- void LogSuccess( void ) ;
- void LogFailure( void ) ;
- void MyInsert(
- Widget w,
- XEvent *event,
- char **params,
- Cardinal *num_params) ;
- void MyCancel(
- Widget w,
- XEvent *event,
- char **params,
- Cardinal *num_params) ;
- void EditPasswdCB(
- Widget w,
- XtPointer client,
- XtPointer call) ;
- void UnknownUser( void ) ;
- void UnknownUserCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData) ;
- /******** End Forward Function Declarations ********/
- /***************************************************************************
- *
- * Text widget actions and translations
- *
- ***************************************************************************/
- XtActionsRec textActions[] = {
- {"my-insert", (XtActionProc)MyInsert},
- {"my-cancel", (XtActionProc)MyCancel},
- };
- char textEventBindings[] = {
- "Shift <Key>Tab: prev-tab-group() \n\
- Ctrl <Key>Tab: next-tab-group() \n\
- <Key>Tab: next-tab-group() \n\
- <Key>osfEndLine: end-of-line() \n\
- <Key>osfBeginLine: beginning-of-line() \n\
- ~Shift <Key>osfRight: forward-character()\n\
- ~Shift <Key>osfLeft: backward-character()\n\
- Ctrl <Key>osfDelete: delete-to-end-of-line()\n\
- <Key>osfDelete: delete-next-character()\n\
- <Key>osfBackSpace: delete-previous-character()\n\
- <Key>osfActivate: activate()\n\
- Ctrl <Key>Return: activate()\n\
- <Key>Return: activate()\n\
- <Key>osfCancel: my-cancel()\n\
- <Key>: my-insert()\n\
- ~Ctrl ~Shift ~Meta ~Alt<Btn1Down>: grab-focus() \n\
- <EnterWindow>: enter()\n\
- <LeaveWindow>: leave()\n\
- <FocusIn>: focusIn()\n\
- <FocusOut>: focusOut()\n\
- <Unmap>: unmap()"
- };
- /****************************************************************************/
- /****************************************************************************/
- static Widget toplevel;
- static ApplArgs appArgs;
- static XtAppContext appContext;
- static DtActionInvocationID actionId;
- static Boolean exitAfterInvoked = False;
- static int exitStatus = 0;
- /* ARGSUSED */
- void
- CheckForDone(
- XtPointer clientData,
- XtIntervalId id)
- {
- if ( toplevel->core.num_popups == 0 )
- exit(exitStatus);
- XtAppAddTimeOut(appContext,
- 10, (XtTimerCallbackProc)CheckForDone,
- NULL);
- }
- int
- main(
- int argc,
- char **argv )
- {
- Display *display;
- Arg args[20];
- int n=0;
- char *actionName;
- int numArgs = 0;
- DtActionArg *ap = NULL;
-
- XtSetLanguageProc(NULL, NULL, NULL);
- _DtEnvControl(DT_ENV_SET);
- (void) signal(SIGCHLD, (void (*)())SIG_IGN);
- /* Initialize the toolkit and open the display */
- XtToolkitInitialize() ;
- appContext = XtCreateApplicationContext() ;
- if ( !(display = XtOpenDisplay( appContext, NULL, argv[0], "Dtaction",
- option_list,
- sizeof(option_list)/sizeof(XrmOptionDescRec),
- &argc, argv)) )
- {
- setlocale(LC_ALL, "");
- fprintf(stderr, "%s", GETMESSAGE(1,11,"Can't open display.\n"));
- exit(-1);
- }
-
- XtSetArg(args[n], XmNallowShellResize, True); n++;
- XtSetArg(args[n], XmNmappedWhenManaged, False); n++;
- XtSetArg(args[n], XmNheight, 1); n++;
- XtSetArg(args[n], XmNwidth, 1); n++;
- toplevel = XtAppCreateShell( argv[0], "Dtaction",
- topLevelShellWidgetClass, display, args, n) ;
- XtRealizeWidget(toplevel);
- display = XtDisplay (toplevel);
- XtGetApplicationResources(toplevel, &appArgs,
- resources, XtNumber(resources), NULL, 0);
- password = XtMalloc(1);
- password[0] = '\0';
- stars = XtMalloc(1);
- stars[0] = '\0';
- /* Get Dt initialized */
- if (DtInitialize (display, toplevel, argv[0], "Dtaction") == False)
- {
- /* Fatal Error: could not connect to the messaging system. */
- /* DtInitialize() has already logged an appropriate error msg */
- exit(-1);
- }
- /*
- * If the request specified that it wanted to run as a different
- * user, then take care of prompting for a password, and doing any
- * necessary verification and logging.
- */
- CheckUserRequest();
-
- /* Load the filetype/action dbs; DtInvokeAction() requires this */
- DtDbLoad();
- /*
- * Get the requested action name
- */
- if ( (actionName = argv[1]) == NULL)
- {
- fprintf(stderr, "%s", GETMESSAGE(1,10,"No action name specified.\n"));
- exit(-1);
- }
- if ( argc > 2 )
- {
- /*
- * create an action arg array for the file objects for
- * this action. This number of objects should be one
- * less than the argument count. The returned vector will
- * be terminated by a null pointer.
- */
- numArgs= argc - 2;
- ap = (DtActionArg *) XtCalloc(numArgs,sizeof(DtActionArg));
- }
- /*
- * This client is restricted to FILE arguments.
- * for the time being.
- */
- for ( n = 0; n < numArgs; n++) {
- ap[n].argClass = DtACTION_FILE;
- ap[n].u.file.name = argv[n+2];
- }
- actionId = DtActionInvoke(toplevel, actionName, ap, numArgs,
- appArgs.termOpts,
- appArgs.execHost,
- appArgs.contextDir,
- True, /* use indicator */
- (DtActionCallbackProc) actionStatusCallback,
- NULL);
- /*
- * Set up a timer if we didn't get a valid procId -- since there will
- * be no invocation update in that case.
- * We must invoke XtMainLoop() at least once, to force any prompt or
- * error dialogs to get posted.
- */
- if ( !actionId)
- XtAppAddTimeOut(appContext,
- 10, (XtTimerCallbackProc)CheckForDone,
- NULL);
- XtAppMainLoop(appContext);
- return EXIT_SUCCESS;
- }
- static void
- SetGidUid ( unsigned short rgid, unsigned short ruid )
- {
- /* fix process gid */
- #if defined(SVR4) || defined(_AIX)
- setgid(rgid);
- #elif defined(__linux__) || defined(CSRG_BASED)
- if(-1 == setregid(rgid, rgid)) {
- fprintf(stderr, "SetGidUid: setregid failed on %d\n", rgid);
- }
- setregid(rgid, rgid);
- #endif
- /* fix process uid */
- #if defined (SVR4) || defined (_AIX)
- setuid(ruid);
- #elif defined(__linux__) || defined(CSRG_BASED)
- if(-1 == setreuid(ruid, ruid)) {
- fprintf(stderr, "SetGidUid: setreuid failed on %d\n", ruid);
- }
- setreuid(ruid, ruid);
- #endif
- }
- /*
- * This function checks to see if the user has requested that the action
- * be invoked under a different user Id. If a different user Id has been
- * requested, then the user will be prompted to enter either the password
- * for that user, or the root password. Once a valid password has been
- * entered, this function will return.
- */
- void
- CheckUserRequest( void )
- {
- unsigned short ruid;
- unsigned short rgid;
- struct passwd * passwd;
- #ifdef sun
- struct spwd * spwd;
- #endif
- Boolean notExist = False;
- Boolean alreadySetToRoot = False;
- rootRequest = False;
- /* get current group id */
- rgid = getgid();
- /* get current user id */
- ruid = getuid();
- /* See if the user wants to run as himself */
- if (appArgs.user == NULL)
- {
- SetGidUid(rgid,ruid);
- return;
- }
- /* Get password for the requested user */
- passwd = getpwnam(appArgs.user);
- if (passwd) {
- #ifdef sun
- spwd = getspnam(appArgs.user);
- if (spwd)
- {
- #endif
- if (passwd->pw_uid == ruid)
- {
- /*
- * We are already running as the
- * requested user. So return now.
- */
- SetGidUid(rgid,ruid);
- return;
- }
- #ifdef sun
- if (spwd->sp_pwdp)
- toPword = XtNewString(spwd->sp_pwdp);
- }
- #else
- if (passwd->pw_passwd)
- toPword = XtNewString(passwd->pw_passwd);
- #endif /* sun */
- basegid = passwd->pw_gid;
- newuid = passwd->pw_uid;
- }
- else
- notExist = True;
- /* Root requests require some extra work later */
- if (strcmp(appArgs.user, "root") == 0)
- rootRequest = True;
- /* Get name for the current user */
- passwd = getpwuid(ruid);
- if (passwd && passwd->pw_name)
- origName = XtNewString(passwd->pw_name);
- /* Get password for the root user */
- passwd = getpwnam("root");
- if (passwd && passwd->pw_passwd)
- {
- #ifdef sun
- spwd = getspnam("root");
- if (spwd && spwd->sp_pwdp)
- {
- rootPword = XtNewString(spwd->sp_pwdp);
- }
- #else
- rootPword = XtNewString(passwd->pw_passwd);
- #endif /* sun */
- if (passwd->pw_uid == ruid)
- alreadySetToRoot = True;
- }
- /*
- * If 'alreadySetToRoot' is set to True, then that means that the
- * user is currently running as root.
- */
- if (notExist)
- {
- /* Requested user does not exist; this function will exit() */
- UnknownUser();
- }
- else if ((alreadySetToRoot) || /* requested users passwd is null */
- ((toPword && (toPword[0] == '\0')) || (toPword == NULL)))
- {
- /* Already there -- no need to check a passwd */
- LogSuccess();
- }
- else
- CheckPasswd();
- }
- /**********
- * void CheckPasswd ()
- *
- * get a password from the user and check it against an encrypted passwd
- *
- * Returns:
- * 0 if invalid
- * True if valid
- *
- * Side Effects:
- * none.
- */
- void
- CheckPasswd( void )
- {
- /*
- * get this users password
- */
- GetUserPrompt();
- }
- /**********
- * void AddSuLog (FromName, ToName, ChangeType)
- *
- * add switch from user "FromName" to user "ToName" to sulog.
- * ChangeType is "+" for success, "-" for failure.
- *
- * Parameters:
- * char *FromName -- from name (for logging).
- * char *ToName -- to name (for logging).
- * char *ChangeType -- +/- (for logging).
- */
- void
- AddSuLog(
- char *FromName,
- char *ToName,
- char *ChangeType )
- {
- char *toString;
- struct tm *localtime ();
- FILE * f;
- struct stat st;
- time_t timenow;
- struct tm *now;
- char * SULog = "/var/adm/sulog";
- if ((f = fopen (SULog, "a")) == NULL)
- return;
- (void) time (&timenow);
- now = localtime (&timenow);
- /* build toString... */
- if (ToName && *ToName)
- toString = ToName;
- else
- toString = FromName;
- fprintf(f, (GETMESSAGE(1,1,
- "dtaction %1$.2d/%2$.2d %3$.2d:%4$.2d %5$1.1s %6$s %7$s-%8$s\n")),
- now -> tm_mon + 1, now -> tm_mday, now -> tm_hour,
- now -> tm_min, ChangeType, "?", FromName, toString);
- (void) fclose (f);
- /*
- * take away write access from SULog
- */
- if(chmod (SULog, 0400) == -1) {
- fprintf(stderr, "Error on chmod of '%s', %s\n", SULog, strerror(errno));
- }
- return;
- }
- /**********
- * void CleanPath (Path);
- *
- * remove any directories from the path that are
- * - null (leading/trailing colon or double colon)
- * - not anchored to root (no leading /)
- *
- * the returned path is the original path with any such
- * directories stripped
- *
- * Parameters:
- * char *Path -- $PATH to clean
- *
- * Returns:
- * none.
- *
- * Side Effects:
- * Unanchored paths will be stripped off of Path.
- */
- void
- CleanPath(
- char *Path )
- {
- char *StrippedPath;
- char *PathHead;
- StrippedPath = PathHead = Path;
- while (*Path) {
- /*
- * remove multiple ':'s
- */
- while (*Path && (*Path == ':')) {
- (void) Path++;
- }
- /*
- * is the first character of this
- * directory a '/'????
- */
- if (*Path == '/') {
- /*
- * copy directory intact;
- */
- while (*Path && (*Path != ':')) {
- *StrippedPath++ = *Path++;
- }
- if (*Path == ':') {
- *StrippedPath++ = *Path++;
- }
- }
- else {
- /*
- * zip past directory
- */
- while (*Path && (*Path != ':')) {
- (void) Path++;
- }
- if (*Path == ':') {
- (void) Path++;
- }
- }
- }
- /*
- * remove all trailing ':'s
- */
- while ((StrippedPath > PathHead) && (StrippedPath[-1] == ':')) {
- StrippedPath--;
- }
- /*
- * null terminate the path
- */
- *StrippedPath = '\0';
- return;
- }
- /*
- * This is the Ok callback for the password dialog. It will attempt to
- * validate the password. If invalid, then an error dialog is posted,
- * and the user is prompted to try again. If valid, then the process
- * will change to run as the requested user, and dtaction will continue
- * on its way, attempting to invoke the requested action.
- */
- /* ARGSUSED */
- void
- OkCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData )
- {
- Boolean valid = False;
- /* Do any verification here */
- /* check for primary passwd... */
- if (!strcmp (crypt (password, toPword), toPword))
- valid = True;
- /* check for secondary passwd ... */
- if (rootPword && *rootPword &&
- !strcmp (crypt (password, rootPword), rootPword))
- {
- valid = True;
- }
- else if (((rootPword == NULL) || (*rootPword == '\0')) &&
- (*password == '\0'))
- {
- /* No root password, and the user entered no password */
- valid = True;
- }
- /* If valid password, then unpost */
- if (valid)
- {
- XtUnmanageChild(dlog);
- XFlush(XtDisplay(dlog));
- finished = True;
- LogSuccess();
- }
- else
- {
- /* Invalid password */
- Widget err;
- int n;
- Arg args[10];
- XmString okLabel;
- XmString message;
- char * template;
- char * title;
- char * master;
- okLabel = XmStringCreateLocalized(GETMESSAGE(1, 2, "OK"));
- template = (GETMESSAGE(1,3, "The password you entered does not match\nthe password for user %s.\n\nPlease reenter the password, or select the\nCancel button to terminate the operation."));
- master = XtMalloc(strlen(template) + strlen(appArgs.user) + 10);
- sprintf(master, template, appArgs.user);
- message = XmStringCreateLocalized(master);
- title = (GETMESSAGE(1,4, "Action Invoker - Password Error"));
- /* Post an error dialog */
- n = 0;
- XtSetArg(args[n], XmNtitle, title); n++;
- XtSetArg(args[n], XmNmessageString, message); n++;
- XtSetArg(args[n], XmNokLabelString, okLabel); n++;
- err = XmCreateErrorDialog(dlog, "err", args, n);
- XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON));
- XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON));
- XtManageChild(err);
- XtAddCallback(err, XmNokCallback, ErrOkCallback, err);
- XFlush(XtDisplay(dlog));
- XmUpdateDisplay(dlog);
- LogFailure();
- XmStringFree(okLabel);
- XmStringFree(message);
- XtFree(master);
- }
- }
- /*
- * This is the Cancel callback for the password dialog. It will unpost
- * the dialog, and exit.
- */
- /* ARGSUSED */
- void
- CancelCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData )
- {
- XtUnmanageChild(dlog);
- XFlush(XtDisplay(dlog));
- exit(-1);
- }
- /*
- * This is the 'Ok' callback for the invalid password error dialog.
- * It will simply unpost and destroy the error dialog.
- */
- /* ARGSUSED */
- void
- ErrOkCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData )
- {
- Widget err = (Widget)clientData;
- XtUnmanageChild(err);
- XFlush(XtDisplay(err));
- XmUpdateDisplay(err);
- XtDestroyWidget(err);
- }
- /*
- * This callback is invoked when the password dialog is posted; it forces
- * the focus to the text input field.
- */
- /* ARGSUSED */
- void
- MapCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData )
- {
- Widget text;
- Widget dlog = (Widget)clientData;
- /* Force focus initially to the text field */
- text = XmSelectionBoxGetChild(dlog, XmDIALOG_TEXT);
- XmProcessTraversal(text, XmTRAVERSE_CURRENT);
- }
- /*
- * This function creates the prompt dialog for collecting the password
- * from the user. It will not give up control until a valid password
- * has been entered. If the user cancels the request, then the cancel
- * callback will exit.
- */
- void
- GetUserPrompt( void )
- {
- int n;
- XmString xmString;
- XmString xmString2;
- char prompt[BUFSIZ];
- Widget help;
- Widget text;
- XEvent event;
- Arg args[10];
- XtTranslations textTable;
- XmString cancelLabel;
- XmString okLabel;
- snprintf(prompt, sizeof prompt, (GETMESSAGE(1,5, "Enter password for user %s:")),
- appArgs.user);
- xmString = XmStringCreateLocalized(prompt);
- xmString2 =XmStringCreateLocalized(GETMESSAGE(1,6, "Action Invoker - Password"));
- cancelLabel = XmStringCreateLocalized(GETMESSAGE(1,7, "Cancel"));
- okLabel = XmStringCreateLocalized(GETMESSAGE(1,2, "OK"));
- XtAppAddActions(appContext,textActions, 2);
- textTable = XtParseTranslationTable(textEventBindings);
- /* Create the prompt dialog */
- n = 0;
- XtSetArg(args[n], XmNselectionLabelString, xmString); n++;
- XtSetArg(args[n], XmNdialogTitle, xmString2); n++;
- XtSetArg(args[n], XmNautoUnmanage, False); n++;
- XtSetArg(args[n], XmNokLabelString, okLabel); n++;
- XtSetArg(args[n], XmNcancelLabelString, cancelLabel); n++;
- XtSetArg(args[n], XmNdefaultPosition, False); n++;
- dlog = XmCreatePromptDialog(toplevel, "prompt", args, n);
- XmStringFree(xmString);
- XmStringFree(xmString2);
- XmStringFree(okLabel);
- XmStringFree(cancelLabel);
- XtAddCallback(dlog, XmNokCallback, OkCallback, NULL);
- XtAddCallback(dlog, XmNcancelCallback, CancelCallback, NULL);
- text = XmSelectionBoxGetChild(dlog, XmDIALOG_TEXT);
- n = 0;
- XtSetArg(args[n], XmNtranslations, textTable); n++;
- XtSetArg(args[n], XmNverifyBell, False); n++;
- XtSetValues(text, args, n);
- XtAddCallback(text, XmNmodifyVerifyCallback, EditPasswdCB, NULL);
- /* Add callback for forcing traversal to the text field */
- XtAddCallback (XtParent(dlog), XmNpopupCallback, MapCallback, dlog);
- /* Unmanage the help button */
- help = XmSelectionBoxGetChild(dlog, XmDIALOG_HELP_BUTTON);
- XtUnmanageChild(help);
- /* Center the dialog */
- XtRealizeWidget(dlog);
- XtSetArg (args[0], XmNx,
- (Position)(WidthOfScreen(XtScreen(dlog)) -
- dlog->core.width) / 2);
- XtSetArg (args[1], XmNy,
- (Position)(HeightOfScreen(XtScreen(dlog)) -
- dlog->core.height) / 2);
- XtSetValues (dlog, args, 2);
- /* Set the transient property */
- XSetTransientForHint (XtDisplay (toplevel),
- XtWindow (XtParent (dlog)),
- XtWindow (toplevel));
- /* Adjust the decorations for the dialog shell of the dialog */
- n = 0;
- XtSetArg(args[n], XmNmwmFunctions, 0); n++;
- XtSetArg(args[n], XmNmwmDecorations,
- MWM_DECOR_BORDER | MWM_DECOR_TITLE); n++;
- XtSetValues(XtParent(dlog), args, n);
- /* Post the dialog */
- XtManageChild(dlog);
- /* Wait for the user to finish with the dialog */
- while (!finished)
- {
- XtAppNextEvent(appContext,&event);
- XtDispatchEvent(&event);
- }
- /* Destroy the widget, and return any data back to the appl */
- XtDestroyWidget(dlog);
- }
- /*
- * When a user has successfully logged in as another user, we need to set
- * the uid and gid to the requested user. In addition, if the user is
- * changing to 'root', then we need to log this in /usr/adm/sulog, and
- * we need to do some housekeeping of the $PATH environment variable.
- */
- void
- LogSuccess( void )
- {
- char * path;
- char * tmpPath;
- AddSuLog(origName, appArgs.user, "+");
- if (rootRequest)
- {
- /* Special stuff for the root user */
- /* Cleanse the $PATH setting */
- tmpPath = getenv("PATH");
- path = XtNewString(tmpPath);
- CleanPath (path);
- tmpPath = XtMalloc(strlen(path) + 10);
- strcpy(tmpPath, "PATH=");
- strcat(tmpPath, path);
- putenv(tmpPath);
- }
- /* Set up the user's new id's */
- SetGidUid(basegid,newuid);
- initgroups(appArgs.user, basegid);
- }
- /*
- * Each time the user enters an invalid password, we need to log this in
- * /usr/adm/sulog, if the user is attempting to switch to the 'root' user.
- */
- void
- LogFailure( void )
- {
- /* Unable to change to specified user; post error, then exit */
- AddSuLog(origName, appArgs.user, "-");
- }
- /***************************************************************************
- *
- * MyInsert
- *
- * Local self-insert action for the text widget. The default action
- * discards control characters, which are allowed in password.
- ***************************************************************************/
- /* ARGSUSED */
- void
- MyInsert(
- Widget w,
- XEvent *event,
- char **params,
- Cardinal *num_params )
- {
- char str[32];
- XComposeStatus compstatus;
- int n;
- n = XLookupString((XKeyEvent *)event, str, sizeof(str),
- (KeySym *)NULL, &compstatus);
- if (n > 0) {
- str[n] = '\0';
- XmTextFieldInsert(w, XmTextFieldGetInsertionPosition(w), str);
- }
- }
- /***************************************************************************
- *
- * MyCancel
- *
- * This action catches the 'Escape' key, and following Motif standards,
- * unposts the dialog, as if the 'Cancel' button had been pressed.
- ***************************************************************************/
- /* ARGSUSED */
- void
- MyCancel(
- Widget w,
- XEvent *event,
- char **params,
- Cardinal *num_params )
- {
- CancelCallback(w, NULL, NULL);
- }
- /***************************************************************************
- *
- * EditPasswdCB
- *
- * implement no-echo of the password
- ***************************************************************************/
- /* ARGSUSED */
- void
- EditPasswdCB(
- Widget w,
- XtPointer client,
- XtPointer call )
- {
- static Boolean allow_flag = False;
- int replaced_length, i;
- char *src, *dst;
- XmTextVerifyPtr cbData = (XmTextVerifyPtr) call;
-
- if (!allow_flag)
- {
- /*
- * we need to keep track of the password ourselves in order to
- * disable echoing of the password...
- */
-
- replaced_length = cbData->endPos - cbData->startPos;
- if (replaced_length > cbData->text->length)
- {
- /* shift the text at and after endPos to the left... */
- for (src = password + cbData->endPos,
- dst = src + (cbData->text->length - replaced_length),
- i = passwordLength - cbData->endPos;
- i > 0;
- ++src, ++dst, --i)
- {
- *dst = *src;
- }
- }
- else if (replaced_length < cbData->text->length)
- {
- /* Buffer must grow */
- password = XtRealloc(password,
- passwordLength + cbData->text->length - replaced_length + 5);
- /* shift the text at and after endPos to the right... */
- for (src = password + passwordLength - 1,
- dst = src + (cbData->text->length - replaced_length),
- i = passwordLength - cbData->endPos;
- i > 0;
- --src, --dst, --i)
- {
- *dst = *src;
- }
- }
-
- /*
- * update the password...
- */
- for (src = cbData->text->ptr,
- dst = password + cbData->startPos,
- i = cbData->text->length;
- i > 0;
- ++src, ++dst, --i)
- {
- *dst = *src;
- }
- passwordLength += cbData->text->length - replaced_length;
- password[passwordLength] = '\0';
- stars = XtRealloc(stars, cbData->text->length + 10);
- for (i = 0; i < cbData->text->length; i++)
- stars[i] = ' ';
- stars[cbData->text->length] = '\0';
-
- /*
- * put the appropriate number of stars in the passwd Widget..
- */
- allow_flag = True;
- XmTextFieldReplace(w, cbData->startPos, cbData->endPos, stars);
- allow_flag = False;
- }
-
- cbData->doit = allow_flag;
- }
- /*
- * This function posts an error dialog informing the user that they have
- * specified an invalid user name. No further processing will be done; we
- * will simply wait for the user to acknowledge the error, and then exit.
- */
- void
- UnknownUser( void )
- {
- Widget err;
- int n;
- Arg args[10];
- XmString okLabel;
- XmString message;
- char * template;
- char * title;
- char * master;
- okLabel = XmStringCreateLocalized(GETMESSAGE(1,2, "OK"));
- template = (GETMESSAGE(1,8, "The user '%s' is an unknown user name.\n\nThe requested action will not be executed."));
- master = XtMalloc(strlen(template) + strlen(appArgs.user) + 10);
- sprintf(master, template, appArgs.user);
- message = XmStringCreateLocalized(master);
- title = (GETMESSAGE(1,9, "Action Invoker - Unknown User"));
- /* Post an error dialog */
- n = 0;
- XtSetArg(args[n], XmNtitle, title); n++;
- XtSetArg(args[n], XmNmessageString, message); n++;
- XtSetArg(args[n], XmNokLabelString, okLabel); n++;
- XtSetArg(args[n], XmNdefaultPosition, False); n++;
- err = XmCreateErrorDialog(toplevel, "err", args, n);
- XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON));
- XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON));
- /* Center the dialog */
- XtRealizeWidget(err);
- XtSetArg (args[0], XmNx,
- (Position)(WidthOfScreen(XtScreen(err)) -
- err->core.width) / 2);
- XtSetArg (args[1], XmNy,
- (Position)(HeightOfScreen(XtScreen(err)) -
- err->core.height) / 2);
- XtSetValues (err, args, 2);
- XtManageChild(err);
- XtAddCallback(err, XmNokCallback, UnknownUserCallback, err);
- XtAddCallback(err, XmNcancelCallback, UnknownUserCallback, err);
- XFlush(XtDisplay(toplevel));
- XmUpdateDisplay(toplevel);
- LogFailure();
- XmStringFree(okLabel);
- XmStringFree(message);
- XtFree(master);
- XtAppMainLoop(appContext);
- }
- /*
- * This is the 'Cancel' callback for the 'Invalid User' error dialog.
- * It removes the dialog, and then exits.
- */
- /* ARGSUSED */
- void
- UnknownUserCallback(
- Widget w,
- XtPointer clientData,
- XtPointer callData )
- {
- Widget err = (Widget)clientData;
- XtUnmanageChild(err);
- XFlush(XtDisplay(err));
- XmUpdateDisplay(err);
- exit(-1);
- }
- void actionStatusCallback(
- DtActionInvocationID id,
- XtPointer client_data,
- DtActionArg *aap,
- int aac,
- DtActionStatus status )
- {
- switch( status ) {
- case DtACTION_INVOKED:
- /*
- * There may still be error dialogs to post so we must return
- * to mainLoop before exiting.
- */
- if ( exitAfterInvoked )
- XtAppAddTimeOut(appContext,
- 10 , (XtTimerCallbackProc)CheckForDone,
- NULL);
- break;
- case DtACTION_DONE:
- XtAppAddTimeOut(appContext,
- 10 , (XtTimerCallbackProc)CheckForDone,
- NULL);
- break;
- case DtACTION_FAILED:
- case DtACTION_CANCELED:
- exitStatus = 1;
- XtAppAddTimeOut(appContext,
- 10 , (XtTimerCallbackProc)CheckForDone,
- NULL);
- break;
- default:
- break;
- }
- }
|