Main.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: Main.c /main/18 1998/07/23 17:56:36 mgreess $ */
  24. /*****************************************************************************
  25. *****************************************************************************
  26. **
  27. ** File: Main.c
  28. **
  29. ** Project: DT
  30. **
  31. ** Description: This file contains the main program for dtaction.
  32. **
  33. **
  34. **(c) Copyright 1993, 1994 Hewlett-Packard Company
  35. **(c) Copyright 1993, 1994 International Business Machines Corp.
  36. **(c) Copyright 1993, 1994 Sun Microsystems, Inc.
  37. **(c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
  38. **
  39. **
  40. ****************************************************************************
  41. ************************************<+>*************************************/
  42. #include <stdlib.h>
  43. #include <limits.h>
  44. #include <stddef.h>
  45. #include <unistd.h>
  46. #include <Dt/MsgCatP.h>
  47. #include <signal.h>
  48. #include <locale.h>
  49. #include <sys/param.h> /* for MAXPATHLEN and MAXHOSTNAMELEN */
  50. #if defined(sun) || defined(__linux__)
  51. #include <crypt.h>
  52. #include <shadow.h>
  53. #endif
  54. #include <errno.h>
  55. #include <grp.h>
  56. #include <pwd.h>
  57. #include <X11/Intrinsic.h>
  58. #include <Xm/XmP.h>
  59. #include <Xm/Text.h>
  60. #include <Xm/TextF.h>
  61. #include <Xm/SelectioB.h>
  62. #include <Xm/MessageB.h>
  63. #include <Xm/Protocols.h>
  64. #include <Xm/MwmUtil.h>
  65. #include <Dt/Dt.h>
  66. #include <Dt/DbUtil.h>
  67. #include <Dt/CmdInv.h>
  68. #include <Dt/Action.h>
  69. #include <Dt/EnvControlP.h>
  70. /******************************************************************************/
  71. #include <time.h>
  72. /* Command line options */
  73. XrmOptionDescRec option_list[] =
  74. {
  75. { "-user", "user", XrmoptionSepArg, NULL},
  76. { "-contextDir", "contextDir", XrmoptionSepArg, NULL},
  77. { "-execHost", "execHost", XrmoptionSepArg, NULL},
  78. { "-termOpts", "termOpts", XrmoptionSepArg, NULL},
  79. };
  80. typedef struct {
  81. char * user;
  82. char * contextDir;
  83. char * execHost;
  84. char * termOpts;
  85. } ApplArgs, *ApplArgsPtr;
  86. #define LOGIN_STR_LEN 15
  87. #define STAR ' '
  88. Widget dlog;
  89. char *password;
  90. char *stars;
  91. int passwordLength = 0;
  92. Boolean finished = False;
  93. Boolean rootRequest = False;
  94. char * toPword = NULL;
  95. char * rootPword = NULL;
  96. char * origName = "Unknown";
  97. int basegid = -1;
  98. int newuid = -1;
  99. /* Dtaction resources */
  100. XtResource resources[] =
  101. {
  102. {
  103. "user", "User", XmRString, sizeof(char *),
  104. XtOffsetOf(ApplArgs, user), XmRImmediate, (XtPointer) NULL,
  105. },
  106. {
  107. "contextDir", "ContextDir", XmRString, sizeof(char *),
  108. XtOffsetOf(ApplArgs, contextDir), XmRImmediate, (XtPointer) NULL,
  109. },
  110. {
  111. "execHost", "ExecHost", XmRString, sizeof(char *),
  112. XtOffsetOf(ApplArgs, execHost), XmRImmediate, (XtPointer) NULL,
  113. },
  114. {
  115. "termOpts", "TermParms", XmRString, sizeof(char *),
  116. XtOffsetOf(ApplArgs, termOpts), XmRImmediate, (XtPointer) NULL,
  117. },
  118. };
  119. /*
  120. * macro to get message catalog strings
  121. */
  122. #ifndef NO_MESSAGE_CATALOG
  123. # define _CLIENT_CAT_NAME "dtact"
  124. extern char *_DtGetMessage(char *filename, int set, int n, char *s);
  125. # define GETMESSAGE(set, number, string)\
  126. (_DtGetMessage(_CLIENT_CAT_NAME, set, number, string))
  127. #else
  128. # define GETMESSAGE(set, number, string)\
  129. string
  130. #endif
  131. Boolean _DtWmStringsAreEqual(
  132. char *in_str,
  133. char *test_str) ;
  134. void CheckForDone(
  135. XtPointer clientData,
  136. XtIntervalId id) ;
  137. void CheckUserRequest( void ) ;
  138. void CheckPasswd( void ) ;
  139. void AddSuLog(
  140. char *FromName,
  141. char *ToName,
  142. char *ChangeType) ;
  143. void CleanPath(
  144. char *Path) ;
  145. void OkCallback(
  146. Widget w,
  147. XtPointer clientData,
  148. XtPointer callData) ;
  149. void ErrOkCallback(
  150. Widget w,
  151. XtPointer clientData,
  152. XtPointer callData) ;
  153. void CancelCallback(
  154. Widget w,
  155. XtPointer clientData,
  156. XtPointer callData) ;
  157. void MapCallback(
  158. Widget w,
  159. XtPointer clientData,
  160. XtPointer callData) ;
  161. void actionStatusCallback (
  162. DtActionInvocationID id,
  163. XtPointer client_data,
  164. DtActionArg *aap,
  165. int aac,
  166. DtActionStatus status );
  167. void GetUserPrompt( void ) ;
  168. void LogSuccess( void ) ;
  169. void LogFailure( void ) ;
  170. void MyInsert(
  171. Widget w,
  172. XEvent *event,
  173. char **params,
  174. Cardinal *num_params) ;
  175. void MyCancel(
  176. Widget w,
  177. XEvent *event,
  178. char **params,
  179. Cardinal *num_params) ;
  180. void EditPasswdCB(
  181. Widget w,
  182. XtPointer client,
  183. XtPointer call) ;
  184. void UnknownUser( void ) ;
  185. void UnknownUserCallback(
  186. Widget w,
  187. XtPointer clientData,
  188. XtPointer callData) ;
  189. /******** End Forward Function Declarations ********/
  190. /***************************************************************************
  191. *
  192. * Text widget actions and translations
  193. *
  194. ***************************************************************************/
  195. XtActionsRec textActions[] = {
  196. {"my-insert", (XtActionProc)MyInsert},
  197. {"my-cancel", (XtActionProc)MyCancel},
  198. };
  199. char textEventBindings[] = {
  200. "Shift <Key>Tab: prev-tab-group() \n\
  201. Ctrl <Key>Tab: next-tab-group() \n\
  202. <Key>Tab: next-tab-group() \n\
  203. <Key>osfEndLine: end-of-line() \n\
  204. <Key>osfBeginLine: beginning-of-line() \n\
  205. ~Shift <Key>osfRight: forward-character()\n\
  206. ~Shift <Key>osfLeft: backward-character()\n\
  207. Ctrl <Key>osfDelete: delete-to-end-of-line()\n\
  208. <Key>osfDelete: delete-next-character()\n\
  209. <Key>osfBackSpace: delete-previous-character()\n\
  210. <Key>osfActivate: activate()\n\
  211. Ctrl <Key>Return: activate()\n\
  212. <Key>Return: activate()\n\
  213. <Key>osfCancel: my-cancel()\n\
  214. <Key>: my-insert()\n\
  215. ~Ctrl ~Shift ~Meta ~Alt<Btn1Down>: grab-focus() \n\
  216. <EnterWindow>: enter()\n\
  217. <LeaveWindow>: leave()\n\
  218. <FocusIn>: focusIn()\n\
  219. <FocusOut>: focusOut()\n\
  220. <Unmap>: unmap()"
  221. };
  222. /****************************************************************************/
  223. /****************************************************************************/
  224. static Widget toplevel;
  225. static ApplArgs appArgs;
  226. static XtAppContext appContext;
  227. static DtActionInvocationID actionId;
  228. static Boolean exitAfterInvoked = False;
  229. static int exitStatus = 0;
  230. /* ARGSUSED */
  231. void
  232. CheckForDone(
  233. XtPointer clientData,
  234. XtIntervalId id)
  235. {
  236. if ( toplevel->core.num_popups == 0 )
  237. exit(exitStatus);
  238. XtAppAddTimeOut(appContext,
  239. 10, (XtTimerCallbackProc)CheckForDone,
  240. NULL);
  241. }
  242. int
  243. main(
  244. int argc,
  245. char **argv )
  246. {
  247. Display *display;
  248. Arg args[20];
  249. int n=0;
  250. char *actionName;
  251. int numArgs = 0;
  252. DtActionArg *ap = NULL;
  253. XtSetLanguageProc(NULL, NULL, NULL);
  254. _DtEnvControl(DT_ENV_SET);
  255. (void) signal(SIGCHLD, (void (*)())SIG_IGN);
  256. /* Initialize the toolkit and open the display */
  257. XtToolkitInitialize() ;
  258. appContext = XtCreateApplicationContext() ;
  259. if ( !(display = XtOpenDisplay( appContext, NULL, argv[0], "Dtaction",
  260. option_list,
  261. sizeof(option_list)/sizeof(XrmOptionDescRec),
  262. &argc, argv)) )
  263. {
  264. setlocale(LC_ALL, "");
  265. fprintf(stderr, "%s", GETMESSAGE(1,11,"Can't open display.\n"));
  266. exit(-1);
  267. }
  268. XtSetArg(args[n], XmNallowShellResize, True); n++;
  269. XtSetArg(args[n], XmNmappedWhenManaged, False); n++;
  270. XtSetArg(args[n], XmNheight, 1); n++;
  271. XtSetArg(args[n], XmNwidth, 1); n++;
  272. toplevel = XtAppCreateShell( argv[0], "Dtaction",
  273. topLevelShellWidgetClass, display, args, n) ;
  274. XtRealizeWidget(toplevel);
  275. display = XtDisplay (toplevel);
  276. XtGetApplicationResources(toplevel, &appArgs,
  277. resources, XtNumber(resources), NULL, 0);
  278. password = XtMalloc(1);
  279. password[0] = '\0';
  280. stars = XtMalloc(1);
  281. stars[0] = '\0';
  282. /* Get Dt initialized */
  283. if (DtInitialize (display, toplevel, argv[0], "Dtaction") == False)
  284. {
  285. /* Fatal Error: could not connect to the messaging system. */
  286. /* DtInitialize() has already logged an appropriate error msg */
  287. exit(-1);
  288. }
  289. /*
  290. * If the request specified that it wanted to run as a different
  291. * user, then take care of prompting for a password, and doing any
  292. * necessary verification and logging.
  293. */
  294. CheckUserRequest();
  295. /* Load the filetype/action dbs; DtInvokeAction() requires this */
  296. DtDbLoad();
  297. /*
  298. * Get the requested action name
  299. */
  300. if ( (actionName = argv[1]) == NULL)
  301. {
  302. fprintf(stderr, "%s", GETMESSAGE(1,10,"No action name specified.\n"));
  303. exit(-1);
  304. }
  305. if ( argc > 2 )
  306. {
  307. /*
  308. * create an action arg array for the file objects for
  309. * this action. This number of objects should be one
  310. * less than the argument count. The returned vector will
  311. * be terminated by a null pointer.
  312. */
  313. numArgs= argc - 2;
  314. ap = (DtActionArg *) XtCalloc(numArgs,sizeof(DtActionArg));
  315. }
  316. /*
  317. * This client is restricted to FILE arguments.
  318. * for the time being.
  319. */
  320. for ( n = 0; n < numArgs; n++) {
  321. ap[n].argClass = DtACTION_FILE;
  322. ap[n].u.file.name = argv[n+2];
  323. }
  324. actionId = DtActionInvoke(toplevel, actionName, ap, numArgs,
  325. appArgs.termOpts,
  326. appArgs.execHost,
  327. appArgs.contextDir,
  328. True, /* use indicator */
  329. (DtActionCallbackProc) actionStatusCallback,
  330. NULL);
  331. /*
  332. * Set up a timer if we didn't get a valid procId -- since there will
  333. * be no invocation update in that case.
  334. * We must invoke XtMainLoop() at least once, to force any prompt or
  335. * error dialogs to get posted.
  336. */
  337. if ( !actionId)
  338. XtAppAddTimeOut(appContext,
  339. 10, (XtTimerCallbackProc)CheckForDone,
  340. NULL);
  341. XtAppMainLoop(appContext);
  342. return EXIT_SUCCESS;
  343. }
  344. static void
  345. SetGidUid ( unsigned short rgid, unsigned short ruid )
  346. {
  347. /* fix process gid */
  348. #if defined(SVR4) || defined(_AIX)
  349. setgid(rgid);
  350. #elif defined(__linux__) || defined(CSRG_BASED)
  351. if(-1 == setregid(rgid, rgid)) {
  352. fprintf(stderr, "SetGidUid: setregid failed on %d\n", rgid);
  353. }
  354. setregid(rgid, rgid);
  355. #endif
  356. /* fix process uid */
  357. #if defined (SVR4) || defined (_AIX)
  358. setuid(ruid);
  359. #elif defined(__linux__) || defined(CSRG_BASED)
  360. if(-1 == setreuid(ruid, ruid)) {
  361. fprintf(stderr, "SetGidUid: setreuid failed on %d\n", ruid);
  362. }
  363. setreuid(ruid, ruid);
  364. #endif
  365. }
  366. /*
  367. * This function checks to see if the user has requested that the action
  368. * be invoked under a different user Id. If a different user Id has been
  369. * requested, then the user will be prompted to enter either the password
  370. * for that user, or the root password. Once a valid password has been
  371. * entered, this function will return.
  372. */
  373. void
  374. CheckUserRequest( void )
  375. {
  376. unsigned short ruid;
  377. unsigned short rgid;
  378. struct passwd * passwd;
  379. #ifdef sun
  380. struct spwd * spwd;
  381. #endif
  382. Boolean notExist = False;
  383. Boolean alreadySetToRoot = False;
  384. rootRequest = False;
  385. /* get current group id */
  386. rgid = getgid();
  387. /* get current user id */
  388. ruid = getuid();
  389. /* See if the user wants to run as himself */
  390. if (appArgs.user == NULL)
  391. {
  392. SetGidUid(rgid,ruid);
  393. return;
  394. }
  395. /* Get password for the requested user */
  396. passwd = getpwnam(appArgs.user);
  397. if (passwd) {
  398. #ifdef sun
  399. spwd = getspnam(appArgs.user);
  400. if (spwd)
  401. {
  402. #endif
  403. if (passwd->pw_uid == ruid)
  404. {
  405. /*
  406. * We are already running as the
  407. * requested user. So return now.
  408. */
  409. SetGidUid(rgid,ruid);
  410. return;
  411. }
  412. #ifdef sun
  413. if (spwd->sp_pwdp)
  414. toPword = XtNewString(spwd->sp_pwdp);
  415. }
  416. #else
  417. if (passwd->pw_passwd)
  418. toPword = XtNewString(passwd->pw_passwd);
  419. #endif /* sun */
  420. basegid = passwd->pw_gid;
  421. newuid = passwd->pw_uid;
  422. }
  423. else
  424. notExist = True;
  425. /* Root requests require some extra work later */
  426. if (strcmp(appArgs.user, "root") == 0)
  427. rootRequest = True;
  428. /* Get name for the current user */
  429. passwd = getpwuid(ruid);
  430. if (passwd && passwd->pw_name)
  431. origName = XtNewString(passwd->pw_name);
  432. /* Get password for the root user */
  433. passwd = getpwnam("root");
  434. if (passwd && passwd->pw_passwd)
  435. {
  436. #ifdef sun
  437. spwd = getspnam("root");
  438. if (spwd && spwd->sp_pwdp)
  439. {
  440. rootPword = XtNewString(spwd->sp_pwdp);
  441. }
  442. #else
  443. rootPword = XtNewString(passwd->pw_passwd);
  444. #endif /* sun */
  445. if (passwd->pw_uid == ruid)
  446. alreadySetToRoot = True;
  447. }
  448. /*
  449. * If 'alreadySetToRoot' is set to True, then that means that the
  450. * user is currently running as root.
  451. */
  452. if (notExist)
  453. {
  454. /* Requested user does not exist; this function will exit() */
  455. UnknownUser();
  456. }
  457. else if ((alreadySetToRoot) || /* requested users passwd is null */
  458. ((toPword && (toPword[0] == '\0')) || (toPword == NULL)))
  459. {
  460. /* Already there -- no need to check a passwd */
  461. LogSuccess();
  462. }
  463. else
  464. CheckPasswd();
  465. }
  466. /**********
  467. * void CheckPasswd ()
  468. *
  469. * get a password from the user and check it against an encrypted passwd
  470. *
  471. * Returns:
  472. * 0 if invalid
  473. * True if valid
  474. *
  475. * Side Effects:
  476. * none.
  477. */
  478. void
  479. CheckPasswd( void )
  480. {
  481. /*
  482. * get this users password
  483. */
  484. GetUserPrompt();
  485. }
  486. /**********
  487. * void AddSuLog (FromName, ToName, ChangeType)
  488. *
  489. * add switch from user "FromName" to user "ToName" to sulog.
  490. * ChangeType is "+" for success, "-" for failure.
  491. *
  492. * Parameters:
  493. * char *FromName -- from name (for logging).
  494. * char *ToName -- to name (for logging).
  495. * char *ChangeType -- +/- (for logging).
  496. */
  497. void
  498. AddSuLog(
  499. char *FromName,
  500. char *ToName,
  501. char *ChangeType )
  502. {
  503. char *toString;
  504. struct tm *localtime ();
  505. FILE * f;
  506. struct stat st;
  507. time_t timenow;
  508. struct tm *now;
  509. char * SULog = "/var/adm/sulog";
  510. if ((f = fopen (SULog, "a")) == NULL)
  511. return;
  512. (void) time (&timenow);
  513. now = localtime (&timenow);
  514. /* build toString... */
  515. if (ToName && *ToName)
  516. toString = ToName;
  517. else
  518. toString = FromName;
  519. fprintf(f, (GETMESSAGE(1,1,
  520. "dtaction %1$.2d/%2$.2d %3$.2d:%4$.2d %5$1.1s %6$s %7$s-%8$s\n")),
  521. now -> tm_mon + 1, now -> tm_mday, now -> tm_hour,
  522. now -> tm_min, ChangeType, "?", FromName, toString);
  523. (void) fclose (f);
  524. /*
  525. * take away write access from SULog
  526. */
  527. if(chmod (SULog, 0400) == -1) {
  528. fprintf(stderr, "Error on chmod of '%s', %s\n", SULog, strerror(errno));
  529. }
  530. return;
  531. }
  532. /**********
  533. * void CleanPath (Path);
  534. *
  535. * remove any directories from the path that are
  536. * - null (leading/trailing colon or double colon)
  537. * - not anchored to root (no leading /)
  538. *
  539. * the returned path is the original path with any such
  540. * directories stripped
  541. *
  542. * Parameters:
  543. * char *Path -- $PATH to clean
  544. *
  545. * Returns:
  546. * none.
  547. *
  548. * Side Effects:
  549. * Unanchored paths will be stripped off of Path.
  550. */
  551. void
  552. CleanPath(
  553. char *Path )
  554. {
  555. char *StrippedPath;
  556. char *PathHead;
  557. StrippedPath = PathHead = Path;
  558. while (*Path) {
  559. /*
  560. * remove multiple ':'s
  561. */
  562. while (*Path && (*Path == ':')) {
  563. (void) Path++;
  564. }
  565. /*
  566. * is the first character of this
  567. * directory a '/'????
  568. */
  569. if (*Path == '/') {
  570. /*
  571. * copy directory intact;
  572. */
  573. while (*Path && (*Path != ':')) {
  574. *StrippedPath++ = *Path++;
  575. }
  576. if (*Path == ':') {
  577. *StrippedPath++ = *Path++;
  578. }
  579. }
  580. else {
  581. /*
  582. * zip past directory
  583. */
  584. while (*Path && (*Path != ':')) {
  585. (void) Path++;
  586. }
  587. if (*Path == ':') {
  588. (void) Path++;
  589. }
  590. }
  591. }
  592. /*
  593. * remove all trailing ':'s
  594. */
  595. while ((StrippedPath > PathHead) && (StrippedPath[-1] == ':')) {
  596. StrippedPath--;
  597. }
  598. /*
  599. * null terminate the path
  600. */
  601. *StrippedPath = '\0';
  602. return;
  603. }
  604. /*
  605. * This is the Ok callback for the password dialog. It will attempt to
  606. * validate the password. If invalid, then an error dialog is posted,
  607. * and the user is prompted to try again. If valid, then the process
  608. * will change to run as the requested user, and dtaction will continue
  609. * on its way, attempting to invoke the requested action.
  610. */
  611. /* ARGSUSED */
  612. void
  613. OkCallback(
  614. Widget w,
  615. XtPointer clientData,
  616. XtPointer callData )
  617. {
  618. Boolean valid = False;
  619. /* Do any verification here */
  620. /* check for primary passwd... */
  621. if (!strcmp (crypt (password, toPword), toPword))
  622. valid = True;
  623. /* check for secondary passwd ... */
  624. if (rootPword && *rootPword &&
  625. !strcmp (crypt (password, rootPword), rootPword))
  626. {
  627. valid = True;
  628. }
  629. else if (((rootPword == NULL) || (*rootPword == '\0')) &&
  630. (*password == '\0'))
  631. {
  632. /* No root password, and the user entered no password */
  633. valid = True;
  634. }
  635. /* If valid password, then unpost */
  636. if (valid)
  637. {
  638. XtUnmanageChild(dlog);
  639. XFlush(XtDisplay(dlog));
  640. finished = True;
  641. LogSuccess();
  642. }
  643. else
  644. {
  645. /* Invalid password */
  646. Widget err;
  647. int n;
  648. Arg args[10];
  649. XmString okLabel;
  650. XmString message;
  651. char * template;
  652. char * title;
  653. char * master;
  654. okLabel = XmStringCreateLocalized(GETMESSAGE(1, 2, "OK"));
  655. 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."));
  656. master = XtMalloc(strlen(template) + strlen(appArgs.user) + 10);
  657. sprintf(master, template, appArgs.user);
  658. message = XmStringCreateLocalized(master);
  659. title = (GETMESSAGE(1,4, "Action Invoker - Password Error"));
  660. /* Post an error dialog */
  661. n = 0;
  662. XtSetArg(args[n], XmNtitle, title); n++;
  663. XtSetArg(args[n], XmNmessageString, message); n++;
  664. XtSetArg(args[n], XmNokLabelString, okLabel); n++;
  665. err = XmCreateErrorDialog(dlog, "err", args, n);
  666. XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON));
  667. XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON));
  668. XtManageChild(err);
  669. XtAddCallback(err, XmNokCallback, ErrOkCallback, err);
  670. XFlush(XtDisplay(dlog));
  671. XmUpdateDisplay(dlog);
  672. LogFailure();
  673. XmStringFree(okLabel);
  674. XmStringFree(message);
  675. XtFree(master);
  676. }
  677. }
  678. /*
  679. * This is the Cancel callback for the password dialog. It will unpost
  680. * the dialog, and exit.
  681. */
  682. /* ARGSUSED */
  683. void
  684. CancelCallback(
  685. Widget w,
  686. XtPointer clientData,
  687. XtPointer callData )
  688. {
  689. XtUnmanageChild(dlog);
  690. XFlush(XtDisplay(dlog));
  691. exit(-1);
  692. }
  693. /*
  694. * This is the 'Ok' callback for the invalid password error dialog.
  695. * It will simply unpost and destroy the error dialog.
  696. */
  697. /* ARGSUSED */
  698. void
  699. ErrOkCallback(
  700. Widget w,
  701. XtPointer clientData,
  702. XtPointer callData )
  703. {
  704. Widget err = (Widget)clientData;
  705. XtUnmanageChild(err);
  706. XFlush(XtDisplay(err));
  707. XmUpdateDisplay(err);
  708. XtDestroyWidget(err);
  709. }
  710. /*
  711. * This callback is invoked when the password dialog is posted; it forces
  712. * the focus to the text input field.
  713. */
  714. /* ARGSUSED */
  715. void
  716. MapCallback(
  717. Widget w,
  718. XtPointer clientData,
  719. XtPointer callData )
  720. {
  721. Widget text;
  722. Widget dlog = (Widget)clientData;
  723. /* Force focus initially to the text field */
  724. text = XmSelectionBoxGetChild(dlog, XmDIALOG_TEXT);
  725. XmProcessTraversal(text, XmTRAVERSE_CURRENT);
  726. }
  727. /*
  728. * This function creates the prompt dialog for collecting the password
  729. * from the user. It will not give up control until a valid password
  730. * has been entered. If the user cancels the request, then the cancel
  731. * callback will exit.
  732. */
  733. void
  734. GetUserPrompt( void )
  735. {
  736. int n;
  737. XmString xmString;
  738. XmString xmString2;
  739. char prompt[BUFSIZ];
  740. Widget help;
  741. Widget text;
  742. XEvent event;
  743. Arg args[10];
  744. XtTranslations textTable;
  745. XmString cancelLabel;
  746. XmString okLabel;
  747. snprintf(prompt, sizeof prompt, (GETMESSAGE(1,5, "Enter password for user %s:")),
  748. appArgs.user);
  749. xmString = XmStringCreateLocalized(prompt);
  750. xmString2 =XmStringCreateLocalized(GETMESSAGE(1,6, "Action Invoker - Password"));
  751. cancelLabel = XmStringCreateLocalized(GETMESSAGE(1,7, "Cancel"));
  752. okLabel = XmStringCreateLocalized(GETMESSAGE(1,2, "OK"));
  753. XtAppAddActions(appContext,textActions, 2);
  754. textTable = XtParseTranslationTable(textEventBindings);
  755. /* Create the prompt dialog */
  756. n = 0;
  757. XtSetArg(args[n], XmNselectionLabelString, xmString); n++;
  758. XtSetArg(args[n], XmNdialogTitle, xmString2); n++;
  759. XtSetArg(args[n], XmNautoUnmanage, False); n++;
  760. XtSetArg(args[n], XmNokLabelString, okLabel); n++;
  761. XtSetArg(args[n], XmNcancelLabelString, cancelLabel); n++;
  762. XtSetArg(args[n], XmNdefaultPosition, False); n++;
  763. dlog = XmCreatePromptDialog(toplevel, "prompt", args, n);
  764. XmStringFree(xmString);
  765. XmStringFree(xmString2);
  766. XmStringFree(okLabel);
  767. XmStringFree(cancelLabel);
  768. XtAddCallback(dlog, XmNokCallback, OkCallback, NULL);
  769. XtAddCallback(dlog, XmNcancelCallback, CancelCallback, NULL);
  770. text = XmSelectionBoxGetChild(dlog, XmDIALOG_TEXT);
  771. n = 0;
  772. XtSetArg(args[n], XmNtranslations, textTable); n++;
  773. XtSetArg(args[n], XmNverifyBell, False); n++;
  774. XtSetValues(text, args, n);
  775. XtAddCallback(text, XmNmodifyVerifyCallback, EditPasswdCB, NULL);
  776. /* Add callback for forcing traversal to the text field */
  777. XtAddCallback (XtParent(dlog), XmNpopupCallback, MapCallback, dlog);
  778. /* Unmanage the help button */
  779. help = XmSelectionBoxGetChild(dlog, XmDIALOG_HELP_BUTTON);
  780. XtUnmanageChild(help);
  781. /* Center the dialog */
  782. XtRealizeWidget(dlog);
  783. XtSetArg (args[0], XmNx,
  784. (Position)(WidthOfScreen(XtScreen(dlog)) -
  785. dlog->core.width) / 2);
  786. XtSetArg (args[1], XmNy,
  787. (Position)(HeightOfScreen(XtScreen(dlog)) -
  788. dlog->core.height) / 2);
  789. XtSetValues (dlog, args, 2);
  790. /* Set the transient property */
  791. XSetTransientForHint (XtDisplay (toplevel),
  792. XtWindow (XtParent (dlog)),
  793. XtWindow (toplevel));
  794. /* Adjust the decorations for the dialog shell of the dialog */
  795. n = 0;
  796. XtSetArg(args[n], XmNmwmFunctions, 0); n++;
  797. XtSetArg(args[n], XmNmwmDecorations,
  798. MWM_DECOR_BORDER | MWM_DECOR_TITLE); n++;
  799. XtSetValues(XtParent(dlog), args, n);
  800. /* Post the dialog */
  801. XtManageChild(dlog);
  802. /* Wait for the user to finish with the dialog */
  803. while (!finished)
  804. {
  805. XtAppNextEvent(appContext,&event);
  806. XtDispatchEvent(&event);
  807. }
  808. /* Destroy the widget, and return any data back to the appl */
  809. XtDestroyWidget(dlog);
  810. }
  811. /*
  812. * When a user has successfully logged in as another user, we need to set
  813. * the uid and gid to the requested user. In addition, if the user is
  814. * changing to 'root', then we need to log this in /usr/adm/sulog, and
  815. * we need to do some housekeeping of the $PATH environment variable.
  816. */
  817. void
  818. LogSuccess( void )
  819. {
  820. char * path;
  821. char * tmpPath;
  822. AddSuLog(origName, appArgs.user, "+");
  823. if (rootRequest)
  824. {
  825. /* Special stuff for the root user */
  826. /* Cleanse the $PATH setting */
  827. tmpPath = getenv("PATH");
  828. path = XtNewString(tmpPath);
  829. CleanPath (path);
  830. tmpPath = XtMalloc(strlen(path) + 10);
  831. strcpy(tmpPath, "PATH=");
  832. strcat(tmpPath, path);
  833. putenv(tmpPath);
  834. }
  835. /* Set up the user's new id's */
  836. SetGidUid(basegid,newuid);
  837. initgroups(appArgs.user, basegid);
  838. }
  839. /*
  840. * Each time the user enters an invalid password, we need to log this in
  841. * /usr/adm/sulog, if the user is attempting to switch to the 'root' user.
  842. */
  843. void
  844. LogFailure( void )
  845. {
  846. /* Unable to change to specified user; post error, then exit */
  847. AddSuLog(origName, appArgs.user, "-");
  848. }
  849. /***************************************************************************
  850. *
  851. * MyInsert
  852. *
  853. * Local self-insert action for the text widget. The default action
  854. * discards control characters, which are allowed in password.
  855. ***************************************************************************/
  856. /* ARGSUSED */
  857. void
  858. MyInsert(
  859. Widget w,
  860. XEvent *event,
  861. char **params,
  862. Cardinal *num_params )
  863. {
  864. char str[32];
  865. XComposeStatus compstatus;
  866. int n;
  867. n = XLookupString((XKeyEvent *)event, str, sizeof(str),
  868. (KeySym *)NULL, &compstatus);
  869. if (n > 0) {
  870. str[n] = '\0';
  871. XmTextFieldInsert(w, XmTextFieldGetInsertionPosition(w), str);
  872. }
  873. }
  874. /***************************************************************************
  875. *
  876. * MyCancel
  877. *
  878. * This action catches the 'Escape' key, and following Motif standards,
  879. * unposts the dialog, as if the 'Cancel' button had been pressed.
  880. ***************************************************************************/
  881. /* ARGSUSED */
  882. void
  883. MyCancel(
  884. Widget w,
  885. XEvent *event,
  886. char **params,
  887. Cardinal *num_params )
  888. {
  889. CancelCallback(w, NULL, NULL);
  890. }
  891. /***************************************************************************
  892. *
  893. * EditPasswdCB
  894. *
  895. * implement no-echo of the password
  896. ***************************************************************************/
  897. /* ARGSUSED */
  898. void
  899. EditPasswdCB(
  900. Widget w,
  901. XtPointer client,
  902. XtPointer call )
  903. {
  904. static Boolean allow_flag = False;
  905. int replaced_length, i;
  906. char *src, *dst;
  907. XmTextVerifyPtr cbData = (XmTextVerifyPtr) call;
  908. if (!allow_flag)
  909. {
  910. /*
  911. * we need to keep track of the password ourselves in order to
  912. * disable echoing of the password...
  913. */
  914. replaced_length = cbData->endPos - cbData->startPos;
  915. if (replaced_length > cbData->text->length)
  916. {
  917. /* shift the text at and after endPos to the left... */
  918. for (src = password + cbData->endPos,
  919. dst = src + (cbData->text->length - replaced_length),
  920. i = passwordLength - cbData->endPos;
  921. i > 0;
  922. ++src, ++dst, --i)
  923. {
  924. *dst = *src;
  925. }
  926. }
  927. else if (replaced_length < cbData->text->length)
  928. {
  929. /* Buffer must grow */
  930. password = XtRealloc(password,
  931. passwordLength + cbData->text->length - replaced_length + 5);
  932. /* shift the text at and after endPos to the right... */
  933. for (src = password + passwordLength - 1,
  934. dst = src + (cbData->text->length - replaced_length),
  935. i = passwordLength - cbData->endPos;
  936. i > 0;
  937. --src, --dst, --i)
  938. {
  939. *dst = *src;
  940. }
  941. }
  942. /*
  943. * update the password...
  944. */
  945. for (src = cbData->text->ptr,
  946. dst = password + cbData->startPos,
  947. i = cbData->text->length;
  948. i > 0;
  949. ++src, ++dst, --i)
  950. {
  951. *dst = *src;
  952. }
  953. passwordLength += cbData->text->length - replaced_length;
  954. password[passwordLength] = '\0';
  955. stars = XtRealloc(stars, cbData->text->length + 10);
  956. for (i = 0; i < cbData->text->length; i++)
  957. stars[i] = ' ';
  958. stars[cbData->text->length] = '\0';
  959. /*
  960. * put the appropriate number of stars in the passwd Widget..
  961. */
  962. allow_flag = True;
  963. XmTextFieldReplace(w, cbData->startPos, cbData->endPos, stars);
  964. allow_flag = False;
  965. }
  966. cbData->doit = allow_flag;
  967. }
  968. /*
  969. * This function posts an error dialog informing the user that they have
  970. * specified an invalid user name. No further processing will be done; we
  971. * will simply wait for the user to acknowledge the error, and then exit.
  972. */
  973. void
  974. UnknownUser( void )
  975. {
  976. Widget err;
  977. int n;
  978. Arg args[10];
  979. XmString okLabel;
  980. XmString message;
  981. char * template;
  982. char * title;
  983. char * master;
  984. okLabel = XmStringCreateLocalized(GETMESSAGE(1,2, "OK"));
  985. template = (GETMESSAGE(1,8, "The user '%s' is an unknown user name.\n\nThe requested action will not be executed."));
  986. master = XtMalloc(strlen(template) + strlen(appArgs.user) + 10);
  987. sprintf(master, template, appArgs.user);
  988. message = XmStringCreateLocalized(master);
  989. title = (GETMESSAGE(1,9, "Action Invoker - Unknown User"));
  990. /* Post an error dialog */
  991. n = 0;
  992. XtSetArg(args[n], XmNtitle, title); n++;
  993. XtSetArg(args[n], XmNmessageString, message); n++;
  994. XtSetArg(args[n], XmNokLabelString, okLabel); n++;
  995. XtSetArg(args[n], XmNdefaultPosition, False); n++;
  996. err = XmCreateErrorDialog(toplevel, "err", args, n);
  997. XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON));
  998. XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON));
  999. /* Center the dialog */
  1000. XtRealizeWidget(err);
  1001. XtSetArg (args[0], XmNx,
  1002. (Position)(WidthOfScreen(XtScreen(err)) -
  1003. err->core.width) / 2);
  1004. XtSetArg (args[1], XmNy,
  1005. (Position)(HeightOfScreen(XtScreen(err)) -
  1006. err->core.height) / 2);
  1007. XtSetValues (err, args, 2);
  1008. XtManageChild(err);
  1009. XtAddCallback(err, XmNokCallback, UnknownUserCallback, err);
  1010. XtAddCallback(err, XmNcancelCallback, UnknownUserCallback, err);
  1011. XFlush(XtDisplay(toplevel));
  1012. XmUpdateDisplay(toplevel);
  1013. LogFailure();
  1014. XmStringFree(okLabel);
  1015. XmStringFree(message);
  1016. XtFree(master);
  1017. XtAppMainLoop(appContext);
  1018. }
  1019. /*
  1020. * This is the 'Cancel' callback for the 'Invalid User' error dialog.
  1021. * It removes the dialog, and then exits.
  1022. */
  1023. /* ARGSUSED */
  1024. void
  1025. UnknownUserCallback(
  1026. Widget w,
  1027. XtPointer clientData,
  1028. XtPointer callData )
  1029. {
  1030. Widget err = (Widget)clientData;
  1031. XtUnmanageChild(err);
  1032. XFlush(XtDisplay(err));
  1033. XmUpdateDisplay(err);
  1034. exit(-1);
  1035. }
  1036. void actionStatusCallback(
  1037. DtActionInvocationID id,
  1038. XtPointer client_data,
  1039. DtActionArg *aap,
  1040. int aac,
  1041. DtActionStatus status )
  1042. {
  1043. switch( status ) {
  1044. case DtACTION_INVOKED:
  1045. /*
  1046. * There may still be error dialogs to post so we must return
  1047. * to mainLoop before exiting.
  1048. */
  1049. if ( exitAfterInvoked )
  1050. XtAppAddTimeOut(appContext,
  1051. 10 , (XtTimerCallbackProc)CheckForDone,
  1052. NULL);
  1053. break;
  1054. case DtACTION_DONE:
  1055. XtAppAddTimeOut(appContext,
  1056. 10 , (XtTimerCallbackProc)CheckForDone,
  1057. NULL);
  1058. break;
  1059. case DtACTION_FAILED:
  1060. case DtACTION_CANCELED:
  1061. exitStatus = 1;
  1062. XtAppAddTimeOut(appContext,
  1063. 10 , (XtTimerCallbackProc)CheckForDone,
  1064. NULL);
  1065. break;
  1066. default:
  1067. break;
  1068. }
  1069. }