/* SREhttp/2 add-on, 28 Sept 2002

  This addon allows clients to issue commands to the server machine.
  It's sort of a "batch telnet".

                          ----  SETUP NOTE  ------
   As installed, _COMMAND is DISABLED for remote-usage.
   To enable remote-usage, you must set
     CHECK_SECURITY=3 
   in the user-configurable parameters (below)

                            --- -----------------

  Since great mischief can be accomplished if naughty clients
  get access to this add-on, this uses SREhttp/2 dynamic passwords.

  In particular, you'll need a SUPERUSER privilege AND a ?COMMAND:pwd,
  special privilege.  

  Thus, to use _COMMAND you must ...

     Create (in USERS.CFG) an entry with a SUPERUSER privilege, 
     AND with a secret privilege of 
          "?COMMAND:xxx"    (without the  quotes),
     where xxx is a hard-to-guess password (that you will be asked to
     provide before _COMMAND will run).  

 YOU NEED BOTH A SUPERUSER PRIVILEGE, AND A ?COMMAND:xxx SECRET PRIVILEGE!

 Also, if the CHECK_SECURITY user-configurable parameter (set below)
 is greater then  the SECURITY_LEVEL SRE2003 parameter,
  _COMMAND will NOT run.


  Note: as with the DETACH command, you should only use this with commands
        that do not require further user input.

*/

/******* Begin user-changeable parmeters  ***********/

/* Compare this value to the SECURITY_LEVEL parameter of SRE2003.
   If it's greater, then do NOT run _COMMAND.
   Thus, given the default of SECURITY_LEVEL = 1
       CHECK_SECURITY=2  :: never run _COMMAND 
       CHECK_SECURITY=1  :: run _COMMAND only for clients sitting at the server
       CHECK_SECURITY=0  :: run _COMMAND
   Note that CHECK_SECURITY=1 is a bit odd -- since if someone is sitting
   at the server, why would he bother using _COMMAND when he could fire up
   an OS/2 window instead?  Though, given _COMMAND's ability to display
   results, perhaps it's not that flakey!

   CHECK_SECURITY=3 basically disables _COMMAND (for all likely values of
   SECURITY_LEVEL)

  By default, CHECK_SECURITY=2, which disables _COMMAND (given the default
  value of SECURITY_LEVEL=1).

*/

CHECK_SECURITY=2         



/***********  END of user changable section ******************/

parse arg list,servername,verb,tempfile,,
          prog_file,reqnum,verbose,client_ip,privset,,
          uri,host_nickname,id_info,aiter,attribs

if verb=" " then do
  say "This SREhttp/2 addon can not be run in standalone mode."
  exit
end  


signal on syntax name e1 
signal on error name e1 
signal on novalue name e1 

if aiter='' then return 'PRIVS_LOOK '  /* get readily available privileges */


/* First, check for superuser privilege */
if  wordpos('SUPERUSER',translate(privset))=0 then do
  if aiter='' then return 'PRIVS _COMMAND addon requires superuser privileges '
  return 'AUTH  _COMMAND addon requires that you have superuser privileges '
end 

/* now check for the secret privilege */
parse var privset . ',' privset2
authh=sre_reqfield('Authorization')
uname=sre_extract_username(authh)
this_flag='RELOGON:'||uname
resp=sreh2_dynamic_pwd('COMMAND',,privset2,0.02,,,,id_info,this_flag) 

if resp=this_flag then do
  return 'AUTH Please logon as a user other then <tt> 'uname '</tt>'
end 

if resp<>''  then do
    return resp
end 


/* a last gotcha */
ss=sre_value('SECURITY_LEVEL',,'SRESYS')
if CHECK_SECURITY> ss then do
  mm='String Sorry. You have sufficient privileges ...<br>but _COMMAND''s remote access to this server has been disabled.'
  mm=mm||'<br>You will need to edit the user-configurable section of _COMMAND.CMD, setting <br> CHECK_SECURITY='||ss
  mm=mm||'<br>(look in '||PROG_FILE||')'
  foo=sre_command(mm,,id_info)
  return foo
end



crlf='0d0a'x

foo=sre_command("SET LIMITTIMETOTAL ",220)
foo=sre_command("SET LIMITTIMEINACTIVE ",160)

foo=sre_command('SEND NOWAIT EXPIRES 5m  type text/html ',,id_info)

 aa=' <!doctype html public "-//IETF//DTD HTML 2.0//EN">'
 aa=aa||crlf||'<html><head><title>SRE-http: Executing OS/2 Commands on ' servername " </title></head><body>"
 aa=aa||crlf||'<font size=-1><a href="javascript:history.go(-1)">back</a></font>'
 aa=aa||crlf||'<h3 align="center">Executing OS/2 commands on ' servername ' </h3> <hr>'
foo=sre_command('VAR  ',aa,id_info)

acommand=''
astat=0
NTHCMD=0
do until list=""
   acommand=""
   parse var list a1 '&' list
   parse var a1 avar '=' aval
   avar=upper(strip(avar)); aval=strip(aval)

   aval=translate(aval,' ','+') ; aval=sre_packur(aval)

  itype=0
  if avar='COMMAND'  then do
      acommand=aval
   end
   if avar="CODE"   then do
        acommand=strip(aval) ; itype=1
   end  /* Do */
   if pos('=',a1)=0 then acommand=strip(sre_packur(translate(avar,' ','+')))

   if acommand<>"" then  do
     astat=do_it(acommand,itype)
     if astat=1 then leave
     iterate
   end  

end 

if astat=0 then do
  aaa='</pre><hr><em>'||date('n')||' '||time('N')||'</em> </body></html>'
  foo=sre_command('VAR  ',aaa,id_info)

  rcode=sre_command('SEND COMPLETE ',,id_info)
  return rcode
end

return '203 '||sre_extract('bytessent')||'  _Command execution did not complete'


/* \====================================*/

/***Do a OS/2 command , using rxqueue *********/
do_it:procedure expose tempfile  host_nickname  crlf verbose reqnum myqueue id_info NTHCMD
   parse arg acomm,itype

mytid=dostid()
port=dospid()

NTHCMD=NTHCMD+1
myqueue="SREH2_"||port||'_CMD_'||mytid
arc = RxProcQueueExists(myqueue)
didmake=0
select
 when arc<0 then do
   foo=rxqueue('C',myqueue)
   didmake=1
 end
 when arc>0 then do
    oldq=rxqueue('s',myqueue)
    do mm=1 to arc
        pull .
    end
    foo=rxqueue('s',oldq)
 end
 otherwise nop          /* queue exists and is empty */
end


astrg=make_cmdstrg(acomm,myqueue,itype)  /* make the cmdfile (in a string) */
AHR='<HR WIDTH="60%">'
IF NTHCMD=1 THEN AHR=''

if itype=0 then
  aa=AHR||'<table><tr><td bgcolor="gold"> <em>Executing command: </em> <b> '||sre_html_encode(acomm)|| ' </b></td></table> <br><pre>'
else
  aa=AHR||'<table><tr><td bgcolor="gold"><em>Executing REXX program</em>:</td><td bgcolor="#aaaa33"> <pre> ' ||sre_html_encode(acomm)|| ' </pre> </td></table> <br><pre>'

foo=sre_command('var ',aa,id_info)

arc = RxProcQueueExists(myqueue)

anerr=rexxthread("S",astrg) 
foo=rxqueue('s',myqueue)

do forever  /* wait for a ctl-z */
   inq= RxProcQueueExists(myqueue)
   if inq=0 then do             /* no results yet */
       call syssleep(1)         /* wait a second */
       iterate                  /*look again */
   end
   parse pull adesc
   if adesc=''  then iterate

/* 1a signals end of output */ 
   if left(strip(adesc),1)='1a'x then do 
            if strip(substr(adesc,2)) <> reqnum then do
               if verbose>1 then call sre_pmprintf("_COMMAND: Residual results detected and ignored: " substr(adesc,2))
               iterate
            end
            if didmake=1 then foo=rxqueue('d',myqueue)
            return    0    
    end
    adesc=sre_html_encode(adesc)||crlf
    rc=sre_command('VAR',adesc,id_info)
    if rc<0 & rc<>'' then do
          foo=rxqueue('d',myqueue)
          if verbose>0 then call sre_pmprintf('_COMMAND error: queue Disconnected')
          if didmake=1 then foo=rxqueue('d',myqueue)
          return 1
    end  /* Do  rc<0 */
end
if didmake=1 then foo=rxqueue('d',myqueue)
return 0




/**************/
/* make a command file to execute an os/2 command */
make_cmdstrg:procedure expose  reqnum id_info
parse arg todo,theq,itype ; theq=strip(theq)
crlf='0d0a'x
if itype=1 then do 
  todo='signal on syntax name taz ; signal on error name taz ; '||crlf||todo||crlf
  todo=todo||'signal off syntax ; signal off error ; signal boop  '||crlf
  todo=todo||'taz: yow=sigl-5; queue "Error In Code (rc, line, condition): "rc","yow"," condition() ; signal off syntax ; signal off error; '
end  /* Do */
todo=strip(todo)
oof=''
al.1='/* */'
al.2="foo=rxqueue('s','session'); "
al.3='do queued(); pull .; end  ; '
al.4="foo=rxqueue('s','"||theq||"');"
if itype=0 then
   al.5="address cmd '@"|| todo ||" 2>&1 < nul | rxqueue "||theq||" ' ;"
else
   al.5=todo

al.6="foo=rxqueue('s','"||theq||"') ;"

al.7="boop: aa='1a'x||'"||strip(reqnum)||"';queue  aa; "

al.8=' exit 0'
do mm=1 to 8
  oof=oof||al.mm||'0d0a'x
end
return oof


/***********************/
e1: call sre_pmprintf('Error in _COMMAND at line 'sigl','rc)
    return 0

/***************************************/

