lemoncube.com Search: (normal)
Articles
Links
News
Projects

Disclaimer

Motif password prompt and launcher

This is based off some Motif sample code for a password dialog (the link is on my links page somewhere). I just added some bits that will check the password against root's (it doesn't have to be root's) and then setuid to 0 and launch an xterm. ie. Its basically a graphical su command (NB: You'll need to make the executable setuid). Security is undoubtedly poor but at least the source is pretty short. The code below is obviously for Solaris, but you could easily mod it to work on linux.

Also google for 'x11 ssh askpass'. This is a pure xlib program for prompting for a password. You could easily hack it to add in the setuid stuff (hint: acceptAction is the routine that ends up with the password. Just get it to call switch_user from the code below. You also need to do an XFlush(app->dpy) in the cleanUp routine).

/*

  Simple password dialog to launch root process

  based on sample Motif code by Dan Heller and Paula Ferguson

  compile using something like:

  gcc -I/usr/openwin/include -L/usr/openwin/lib -lcrypt -lXm -lXt \
    -lX11 -o d4 d4.c


 * Written by Dan Heller and Paula Ferguson.
 * Copyright 1994, O'Reilly & Associates, Inc.
 * Permission to use, copy, and modify this program without
 * restriction is hereby granted, as long as this copyright
 * notice appears in each copy of the program source code.
 * This program is freely distributable without licensing fees and
 * is provided without guarantee or warrantee expressed or implied.
 * This program is -not- in the public domain.
 */

/* password.c -- prompt for a password. All input looks like
 * a series of *'s.  Store the actual data typed by the user in
 * an internal variable.  Don't allow paste operations.  Handle
 * backspacing by deleting all text from insertion point to the
 * end of text.
 */
#include <stdlib.h>
#include <shadow.h>
#include <unistd.h>
#include <string.h>

#include <Xm/Text.h>
#include <Xm/LabelG.h>
#include <Xm/RowColumn.h>

void check_passwd();
char *passwd; /* store user-typed passwd here. */


void switch_user(char *s) {
   struct spwd *spwd;
   char *epasswd;
   char *disp;
   char cmdline[256];
   int x;


   spwd = getspnam("root");
   if (spwd!=NULL) {
      epasswd = (char *) crypt(s,spwd->sp_pwdp);
      if (strcmp(epasswd,spwd->sp_pwdp)==0) {
         printf("match\n");
         //Zap the password
         for (x=0;s[x]!=0;x++)
            s[x]=0;
         disp = getenv("DISPLAY");
         if (disp!=NULL) {
            printf("disp %s\n",disp);
            snprintf(cmdline,255,"HOME=/ /usr/openwin/bin/xterm -ls -display %s"
,disp);
            setuid(0);
            system(cmdline);
         }

      }

   } else
      printf("bad\n");
}

main(argc, argv)
int argc;
char *argv[];
{
    Widget        toplevel, text_w, rowcol;
    XtAppContext  app;

    XtSetLanguageProc (NULL, NULL, NULL);

    toplevel = XtVaAppInitialize (&app, "Demos",
        NULL, 0, &argc, argv, NULL, NULL);

    rowcol = XtVaCreateWidget ("rowcol",
        xmRowColumnWidgetClass, toplevel,
        XmNorientation, XmHORIZONTAL,
        NULL);

    XtVaCreateManagedWidget ("Password:",
        xmLabelGadgetClass, rowcol, NULL);
    text_w = XtVaCreateManagedWidget ("text_w",
        xmTextWidgetClass, rowcol, NULL);

    XtAddCallback(text_w, XmNmodifyVerifyCallback, check_passwd, NULL);
    XtAddCallback(text_w, XmNactivateCallback, check_passwd, NULL);

    XtManageChild (rowcol);
    XtRealizeWidget (toplevel);
    XtAppMainLoop (app);
}

/* check_passwd() -- handle the input of a password. */
void
check_passwd(text_w, client_data, call_data)
Widget        text_w;
XtPointer     client_data;
XtPointer     call_data;
{
    char *c_new;
    char duppass[100];
    int len;
    XmTextVerifyCallbackStruct *cbs =
        (XmTextVerifyCallbackStruct *) call_data;

    if (cbs->reason == XmCR_ACTIVATE) {
        //printf ("Password: %s\n", passwd);
        strcpy(duppass,passwd);
        XtFree(passwd);
        XtUnmanageChild(text_w);
        XtDestroyWidget(text_w);
        switch_user(duppass);
        exit(1);
    }

    if (cbs->startPos < cbs->currInsert) {   /* backspace */
        cbs->endPos = strlen (passwd);       /* delete from here to end */
        passwd[cbs->startPos] = 0;           /* backspace--terminate */
        return;
    }

    if (cbs->text->length > 1) {
        cbs->doit = False;  /* don't allow "paste" operations */
        return;             /* make the user *type* the password! */
    }

    c_new = XtMalloc (cbs->endPos + 2); /* new char + NULL terminator */
    if (passwd) {
        strcpy (c_new, passwd);
        XtFree (passwd);
    } else
        c_new[0] = (char) NULL;
    passwd = c_new;
    strncat (passwd, cbs->text->ptr, cbs->text->length);
    passwd[cbs->endPos + cbs->text->length] = 0;

    for (len = 0; len < cbs->text->length; len++)
        cbs->text->ptr[len] = '*';
}

pablo , 2004-02-10 22:13:25