Monday, January 24, 2011

Methods to Increase Security on suPHP - Restricting who can use php.ini files

The php.ini file under suPHP

While suPHP has various security enhancements over DSO PHP such as running processes as the user rather than nobody as well as only allowing 755 folder and 644 file permissions, the option to allow individual php.ini files is a glaring security concern.

There are several methods that can be used to disallow users to have their own php.ini files under suPHP. The path you take will depend on whether you want to allow users to have their own in some circumstances or to restrict all accounts on the server to the global php.ini file at /usr/local/lib/php.ini location.

Restrict all accounts to the global php.ini file

To restrict all accounts to the global php.ini file, you would edit the /opt/suphp/etc/suphp.conf file:

Uncomment these lines:
Code:
[phprc_paths]
;Uncommenting these will force all requests to that handler to use the php.ini
;in the specified directory regardless of suPHP_ConfigPath settings.
;application/x-httpd-php=/usr/local/lib/
;application/x-httpd-php4=/usr/local/php4/lib/
;application/x-httpd-php5=/usr/local/lib/
To these:
Code:
[phprc_paths]
;Uncommenting these will force all requests to that handler to use the php.ini
;in the specified directory regardless of suPHP_ConfigPath settings.
application/x-httpd-php=/usr/local/lib/
application/x-httpd-php4=/usr/local/php4/lib/
application/x-httpd-php5=/usr/local/lib/
Save the file, then restart Apache for good measure. Now, if any account tries to put suPHP_ConfigPath into their .htaccess file, that account will return an Internal Server Error until they remove the .htaccess line. No account will be able to use another php.ini file with this as the default unless you allow the account in the php.ini file itself.

If you have PHP 5.3+ and want to allow some accounts to have their own php.ini file

If you have restricted all accounts globally to the /usr/local/lib/php.ini file and want to have one or more accounts bypass the restriction, this is possible under PHP 5.3 using the global php.ini itself.

Method One: Allowing individual user_ini files

In /usr/local/lib/php.ini file, put the following line:

Code:
user_ini.filename = .my.ini
The .my.ini name can be anything. Save the file, then go to the account you want to allow their own settings and create .my.ini on the account (it can be anywhere on the account so /home/username/public_html/.my.ini)

In the .my.ini file, you would be able to put only the changes you want to have such as register_globals = On for that account. Of note, only the PHP_INI_PERDIR and PHP_INI_USER directives are allowed in this file. Any PHP_INI_SYSTEM directives will not be changeable there.

Method Two: Putting individual user settings into the global php.ini file

This is the better method in my opinion. At the bottom of /usr/local/lib/php.ini file, you can actually define individual user php.ini directives with the path to that user's application:

Code:
[PATH=/home/username/public_html]
register_globals=On
post_max_size=5000M
Here is an example putting that at the bottom of /usr/local/lib/php.ini for an account. If you try doing this in PHP 5.2, it will change the global value to the new ones rather than just that user's as PHP 5.2 doesn't support the path directive. Only PHP 5.3 will work properly to read the path to the user's application. Under this method, even PHP_INI_SYSTEM directives are changeable for that account.

Under Method One for the user_ini file, the user does have the ability to themselves modify directives in their .my.ini file on the account. Under Method Two for the global php.ini user path directives, only the administrator of the machine could modify the directives. Of note, anyone can create their own user_ini file under Method One, but they would need to know the name in the global php.ini to do so (since you can call the file anything, so it could be called .guessme.ini instead and users aren't then likely to know the name to bypass restrictions).

If you are using PHP 5.2 or earlier (PHP 5 only, not tested on PHP 4 nor guaranteed to work on PHP 4)

If you are not using PHP 5.3, then the prior methods will not work. This then leads instead to the more complicated option to allow some users to have their own php.ini file and some users to be restricted to the global php.ini file.

Under this method, you cannot have the phprc_paths uncommented, so you must have them commented out. As such, you would need to ensure /opt/suphp/etc/suphp.conf looks like the following for that area:

Code:
[phprc_paths]
;Uncommenting these will force all requests to that handler to use the php.ini
;in the specified directory regardless of suPHP_ConfigPath settings.
;application/x-httpd-php=/usr/local/lib/
;application/x-httpd-php4=/usr/local/php4/lib/
;application/x-httpd-php5=/usr/local/lib/
Now, you would need to do the following steps:

1. Restrict all users to the global php.ini

Create the following directory:
Code:
mkdir -p /usr/local/apache/conf/userdata
Create a file in that directory:
Code:
cd /usr/local/apache/conf/userdata
vi suphp_config.conf
In that file, place the following:
Code:


suPHP_ConfigPath /usr/local/lib
Save the file (:wq). The above will restrict all current users to the /usr/local/lib location for the php.ini file.

2. Allowing one user to have an individual php.ini

Create the following directories:
Code:
mkdir -p /usr/local/apache/conf/userdata/std/2/username
Here, std is for http. If you are also wanting this for https, you'd also create an ssl directory. The 2 is for Apache 2 and 2.2. If you are using Apache 1.3, you'd use 1 instead. The username is the cPanel username, so replace with the correct username.

In that location, create the file:
Code:
cd /usr/local/apache/conf/userdata/std/2/username
vi suphp_config.conf
In that file, place the following:
Code:


suPHP_ConfigPath /home/username/
Again, replace username with the cPanel username. This will allow a php.ini file to be placed into /home/username level only. Save the file (:wq).

3. Adding additional directories

Further directories can be allowed on the user's account who is being allowed to have a php.ini file. If you change the entry to this in
/usr/local/apache/conf/userdata/std/2/username/suphp_config.conf location:

Code:


suPHP_ConfigPath /home/username/{public_html}/{folder1,folder2}
This allows a php.ini in public_html as well as in public_html/folder1 and public_html/folder2 locations.

4. Checking the changes into httpd.conf

Create a backup of Apache in case you need to revert to it:
Code:
cp /usr/local/apache/conf/httpd.conf
/usr/local/apache/conf/httpd.conf.bak100902
Here 100902 is the date where today is September 2, 2010.

Now, run the following command to verify the includes:
Code:
/scripts/verify_vhost_includes
If each checks out OK, you'd then run this command to check these into the system:
Code:
/scripts/ensure_vhost_includes --all-users
Now, rebuild Apache and restart it (rebuilding isn't entirely necessary in this instance, but I normally just do it as a precaution to ensure everything is working fine):
Code:
/scripts/rebuildhttpdconf
/etc/init.d/httpd restart
Two Important Notes on Above Method

1. mod_userdir exception

mod_userdir will bypasses the suPHP_ConfigPath restriction for the global php.ini file. If you have a user with the following url type:

http://hostname/~username/

That url will allow any php.ini files or suPHP_ConfigPath set into .htaccess to parse under mod_userdir. This is unwanted behavior, and the only current way I'm aware to prevent it would be to disable mod_userdir on such a system.

2. New accounts aren't restricted

Any accounts created after you have locked users into the global php.ini file using the tags around suPHP_ConfigPath in userdata location will not be restricted to it. Each time a new account is created, the following must be run after the account creation to lock that account to the global restriction:

Code:
/scripts/ensure_vhost_includes --all-users
/etc/init.d/httpd restart
Final Note: suPHP_ConfigPath in httpd.conf

Defining the suPHP_ConfigPath line in the VirtualHost entry in httpd.conf does not restrict the account to using that path if the tags are not around it. Without those tags, if a user defines the suPHP_ConfigPath into their .htaccess file on their account in either /home/user/ or /home/user/public_html, their .htaccess entry will override the httpd.conf VirtualHost entry. You can only lock users to the set suPHP_ConfigPath by the previously described method.

Wednesday, January 19, 2011

SAPRFC functions

SAPRFC use RFC (remote call function) API to make call a function module in SAP R/3. You can also write RFC server program in PHP and call PHP functions from SAP R/3. Function modules are defined in transaction SE37 (Function Builder). Each function module has interface defined. The interface definition consist from import parameters (input), export parameters (output), internal tables (input/output) and exceptions. The function module have to set RFC support enable to be able called by RFC from a remote system. More information about function modules and programming concepts in SAP R/3 you can find on http://help.sap.com under the BC manuals.
You need to compile PHP with the --with-saprfc parameter to enable this extension. You also need SAP RFCSDK (if you are SAP customer, you can find it on the "Presentation CD").
Table of Contents
saprfc_attributes — Gets some information about RFC connection
saprfc_call_and_receive — Does a remote call of an function module
saprfc_close — Closes a RFC connection
saprfc_error — Gets the last RFC error message
saprfc_exception — Gets a exception string for last call of an function module
saprfc_export — Gets a value of a export parameter
saprfc_function_debug info — Prinst an interface definition of a function module and content of internal buffers
saprfc_function_define — Defines an interface of a function module
saprfc_function_discover — Discovers an interface of a function module
saprfc_function_free — Frees a function module resources
saprfc_function_interface — Gets an interface definition of a function module
saprfc_function_name — Gets the name of function module
saprfc_import — Sets a value of a import parameter
saprfc_server_accept — Accepts an incoming RFC connection
saprfc_server_export — Sets a value of a export parameter
saprfc_server_import — Gets a value of a import parameter
saprfc_server_dispatch — Receives a single RFC request and call a corresponding PHP function
saprfc_server_register_check — Check for registered RFC server at a SAP gateway
saprfc_server_register_cancel — Cancel all registered RFC servers at a SAP gateway
saprfc_set_trace — Activate/Deactivate the RFC trace
saprfc_table_append — Appends a line at end of internal table
saprfc_table_init — Init a internal table
saprfc_table_insert — Inserts a line into an internal table
saprfc_table_modify — Modify a line of an internal table
saprfc_table_read — Reads a line from an internal table
saprfc_table_remove — Removes a line of an internal table
saprfc_table_rows — Gets a number of lines an internal table
saprfc_trfc_call — Calls a function module in R/3 indirectly (tRFC)
saprfc_trfc_dispatch — Receives a single RFC request and call a corresponding PHP function (tRFC)
saprfc_trfc_install — Installs functions to control transactional behaviour (tRFC)
saprfc_trfc_tid — Gets a transaction-ID for a following call of a function module using tRFC
saprfc_open — Open a RFC connection to SAP R/3
saprfc_optional — Set a import parameter as optional
saprfc_set_code_page — Set SAP codepage for a RFC connection
saprfc_allow_start_program — Explicitly allows the RFC library to start the programs
saprfc_get_ticket — Retrieve backend generated cookie version 2 after calling saprfc_open with flag GETSSO2

saprfc_attributes

(PHP 4, PHP 5)
saprfc_attributes  --  Get some information about RFC connection

Description

array saprfc_attributes (int rfc)
Return array with some information about an RFC connection, such as host name, service of the connected application server and SAP gateway, the R/3 system number, client, user and language.
It should be called after saprfc_call_and_receive() or saprfc_server_dispatch().

$attr[dest]field RFC destination
$attr[own_host]Own host name
$attr[partner_host]Partner host name
$attr[systnr]R/3 system number
$attr[sysid]R/3 system name
$attr[client]Client
$attr[user]User
$attr[language]Language
$attr[trace]ON/OFF: 'X'/' '
$attr[ISO_language]2-byte ISO-Language
$attr[own_codepage]Own code page
$attr[partner_codepage]Partner code page
$attr[rfc_role]C/S: RFC Client / RFC Server
$attr[own_type]2/3/E/R: R/2,R/3,Ext,Reg.Ext
$attr[own_rel]My system release
$attr[partner_type]2/3/E/R: R/2,R/3,Ext,Reg.Ext
$attr[partner_rel]Partner system release
$attr[kernel_rel]Partner kernel release
$attr[CPIC_convid]CPI-C Conversation ID

saprfc_call_and_receive

(PHP 4, PHP 5)
saprfc_call_and_receive  --  Do a remote call of an function module

Description

int saprfc_call_and_receive (int fce)
Call a function module defined by function handle fce. Return SAPRFC_OK if the call was successfully completed.
List of SAP RFC return codes:

SAPRFC_OKO.K.
SAPRFC_FAILUREError occurred
SAPRFC_EXCEPTIONException raised
SAPRFC_SYS_EXCEPTIONSystem exception raised, connection closed
SAPRFC_CALLCall received
SAPRFC_INTERNAL_COMInternal communication, repeat (internal use only)
SAPRFC_CLOSEDConnection closed by the other side
SAPRFC_RETRYNo data yet
SAPRFC_NO_TIDNo Transaction ID available
SAPRFC_EXECUTEDFunction already executed
SAPRFC_SYNCHRONIZESynchronous Call in Progress
SAPRFC_MEMORY_INSUFFICIENTMemory insufficient
SAPRFC_VERSION_MISMATCHVersion mismatch
SAPRFC_NOT_FOUNDFunction not found (internal use only)
SAPRFC_CALL_NOT_SUPPORTEDThis call is not supported
SAPRFC_NOT_OWNERCaller does not own the specified handle
SAPRFC_NOT_INITIALIZEDRFC not yet initialized.
SAPRFC_SYSTEM_CALLEDA system call such as RFC_PING for connectiontest is executed
SAPRFC_INVALID_HANDLEAn invalid handle was passed to an API call.
SAPRFC_INVALID_PARAMETERAn invalid parameter was passed to an API call.
SAPRFC_CANCELEDInternal use only

Example 1. Call ABAP function module

$rfc_rc = saprfc_call_and_receive ($fce);
switch ($rfc_rc) {
   case SAPRFC_OK        : break;
   case SAPRFC_EXCEPTION : echo ("Exception raised:".saprfc_exception($fce));
                           // handle exception
   default:              : echo ("RFC error ".saprfc_error());
                           exit;  
}
?>
                 
See also: saprfc_exception(), saprfc_error()

saprfc_close

(PHP 4, PHP 5)
saprfc_close  --  Close a RFC connection

Description

bool saprfc_close (int rfc)
Close a RFC connection.
See also: saprfc_open(), saprfc_server_accept()

saprfc_error

(PHP 4, PHP 5)
saprfc_error  --  Get a last RFC error message

Description

string saprfc_error ()
Get string with more information on RFC errors that have occurred.

saprfc_exception

(PHP 4, PHP 5)
saprfc_exception  --  Get a exception string for last call of an function module

Description

string saprfc_exception (int fce)
Get a exception string for last call of an function module.
See also: saprfc_call_and_receive()

saprfc_export

(PHP 4, PHP 5)
saprfc_export  --  Get a value of a export parameter

Description

mixed saprfc_export (int fce, string name)
Return value of a export parameter name for function handle fce.

Example 1. Set of the import parameter

$NAME = saprfc_export ($fce,"NAME");
   echo ($NAME);
   $FULLNAME = saprfc_export ($fce,"FULLNAME");
   echo ($FULLNAME[FIRST]." ".$FULLNAME[LAST]);
?>
                 
See also: saprfc_import(), saprfc_server_import(), saprfc_server_export()

saprfc_function_debug info

(PHP 4, PHP 5)
saprfc_function_debug info  --  Print an interface definition of a function module and content of internal buffers

Description

void saprfc_function_debug_info (int fce, [bool only_values])
Show debug information for the function handle fce. If only_values is true don't show interface definition, show values of parameters and values of internal tables only.

saprfc_function_define

(PHP 4, PHP 5)
saprfc_function_define  --  Define an interface of a function module

Description

int saprfc_function_define (int rfc, string function_module, array def, [bool not_trim = false])
Define interface of the function_module. The definition is in array def. Return function handle on success or false on failure. You can use saprfc_test.php script to get definition array for selected function module.
For definition of PHP server function can be rfc parameter set to 0.

Example 1: Interface definition for function module RFC_READ_REPORT

$def = array (
      array (
       "name"=>"SYSTEM",
       "type"=>"EXPORT",
       "optional"=>"0",
       "def"=> array (
        array ("name"=>"","abap"=>"C","len"=>8,"dec"=>0,"offset"=>0)
       )
     ),
      array (
       "name"=>"TRDIR",
       "type"=>"EXPORT",
       "optional"=>"0",
       "def"=> array (
        array ("name"=>"NAME","abap"=>"C","len"=>40,"dec"=>0,"offset"=>0),
        array ("name"=>"SQLX","abap"=>"C","len"=>1,"dec"=>0,"offset"=>40),
        array ("name"=>"EDTX","abap"=>"C","len"=>1,"dec"=>0,"offset"=>41),
        array ("name"=>"VARCL","abap"=>"C","len"=>1,"dec"=>0,"offset"=>42),
        array ("name"=>"DBAPL","abap"=>"C","len"=>1,"dec"=>0,"offset"=>43),
        array ("name"=>"DBNA","abap"=>"C","len"=>2,"dec"=>0,"offset"=>44),
        array ("name"=>"CLAS","abap"=>"C","len"=>4,"dec"=>0,"offset"=>46),
        array ("name"=>"TYPE","abap"=>"C","len"=>3,"dec"=>0,"offset"=>50),
        array ("name"=>"OCCURS","abap"=>"C","len"=>1,"dec"=>0,"offset"=>53),
        array ("name"=>"SUBC","abap"=>"C","len"=>1,"dec"=>0,"offset"=>54),
        array ("name"=>"APPL","abap"=>"C","len"=>1,"dec"=>0,"offset"=>55),
        array ("name"=>"SECU","abap"=>"C","len"=>8,"dec"=>0,"offset"=>56),
        array ("name"=>"CNAM","abap"=>"C","len"=>12,"dec"=>0,"offset"=>64),
        array ("name"=>"CDAT","abap"=>"D","len"=>8,"dec"=>0,"offset"=>76),
        array ("name"=>"UNAM","abap"=>"C","len"=>12,"dec"=>0,"offset"=>84),
        array ("name"=>"UDAT","abap"=>"D","len"=>8,"dec"=>0,"offset"=>96),
        array ("name"=>"VERN","abap"=>"C","len"=>6,"dec"=>0,"offset"=>104),
        array ("name"=>"LEVL","abap"=>"C","len"=>4,"dec"=>0,"offset"=>110),
        array ("name"=>"RSTAT","abap"=>"C","len"=>1,"dec"=>0,"offset"=>114),
        array ("name"=>"RMAND","abap"=>"C","len"=>3,"dec"=>0,"offset"=>115),
        array ("name"=>"RLOAD","abap"=>"C","len"=>1,"dec"=>0,"offset"=>118),
        array ("name"=>"FIXPT","abap"=>"C","len"=>1,"dec"=>0,"offset"=>119),
        array ("name"=>"SSET","abap"=>"C","len"=>1,"dec"=>0,"offset"=>120),
        array ("name"=>"SDATE","abap"=>"D","len"=>8,"dec"=>0,"offset"=>121),
        array ("name"=>"STIME","abap"=>"C","len"=>6,"dec"=>0,"offset"=>129),
        array ("name"=>"IDATE","abap"=>"D","len"=>8,"dec"=>0,"offset"=>135),
        array ("name"=>"ITIME","abap"=>"C","len"=>6,"dec"=>0,"offset"=>143),
        array ("name"=>"LDBNAME","abap"=>"C","len"=>20,"dec"=>0,"offset"=>149),
        array ("name"=>"UCCHECK","abap"=>"C","len"=>1,"dec"=>0,"offset"=>169)
       )
     ),
      array (
       "name"=>"PROGRAM",
       "type"=>"IMPORT",
       "optional"=>"0",
       "def"=> array (
        array ("name"=>"","abap"=>"C","len"=>40,"dec"=>0,"offset"=>0)
       )
     ),
      array (
       "name"=>"QTAB",
       "type"=>"TABLE",
       "optional"=>"0",
       "def"=> array (
        array ("name"=>"LINE","abap"=>"C","len"=>72,"dec"=>0,"offset"=>0)
       )
     )
    ); 

   $fce = saprfc_function_define($rfc,"RFC_READ_REPORT",$def);
?>
                 
See also: saprfc_function_discover(), saprfc_function_interface(), saprfc_function_debug_info(), saprfc_function_free()

saprfc_function_discover

(PHP 4, PHP 5)
saprfc_function_discover  --  Discover an interface of a function module

Description

int saprfc_function_discover (int rfc, string function_module, [bool not_trim = false])
Discover an interface of the function_module. Return function handle on success or false on failure. Use function modules RFC_GET_FUNCTION_INTERFACE_P and RFC_GET_STRUCTURE_DEFINITION_P in connected SAP R/3 to get information about the interface.
See also: saprfc_function_define(), saprfc_function_interface(), saprfc_function_debug_info(), saprfc_function_free()

saprfc_function_free

(PHP 4, PHP 5)
saprfc_function_free  --  Free a function module resources

Description

bool saprfc_function_free (int fce)
Free allocated resources for given function handle fce.

saprfc_function_interface

(PHP 4, PHP 5)
saprfc_function_interface  --  Get an interface definition of a function module

Description

array saprfc_function_interface (int fce)
Return interface definition for the function handle fce on success or false on failure. The definition has same format as in the saprfc_function_define().
See also: saprfc_function_define(), saprfc_function_discover()

saprfc_function_name

(PHP 4, PHP 5)
saprfc_function_name  --  Gets the name of function module

Description

string saprfc_function_name (int fce)
Return name of the function module for function handle fce on success or false on failure.

saprfc_import

(PHP 4, PHP 5)
saprfc_import  --  Set a value of a import parameter

Description

bool saprfc_import (int fce, string name, mixed value)
Set a value of the import parameter name. Return true on success or false on failure. The value can be single (string, number....) or structure (hash array - key=name of structure item).

Example 1. Set of the import parameter

saprfc_import ($fce,"NAME","Smith");
   saprfc_import ($fce,"FULLNAME", array ("FIRST"=>"John","LAST"=>"Smith"));
?>
                 
See also: saprfc_export(), saprfc_server_import(), saprfc_server_export()

saprfc_server_accept

(PHP 4, PHP 5)
saprfc_server_accept  --  Accept an incoming RFC connection

Description

int saprfc_server_accept (mixed args)
Accept an incoming RFC connection from SAP gateway and return RFC handle on success or false on failure.
Args parameter is used for registration on SAP Gateway (transaction SM59). The value of parameter can be $argv array or a command line string:

– aprogram ID e.g. own_host_name.program_name
– ghost name of the SAP gateway
– xservice of the SAP gateway e.g. sapgw00
– tUse RFC-trace
Note: The function has different behaviour under Windows and Unix. While under Windows return to caller immediately, under Unix after receive first RFC call. This is behaviour of function RfcAccept() (SAP RFCSDK).

Example 1. Checking Constants

$rfc = saprfc_server_accept ("-a phpgw -g server -x sapgw30");
// or
// $rfc = saprfc_server_accept ($argv);
?>
                 
See also: saprfc_server_dispatch()

saprfc_server_export

(PHP 4, PHP 5)
saprfc_server_export  --  Set a value of a export parameter

Description

bool saprfc_server_export (int fce, string name, mixed value)
Set a value of the export parameter name. Return true on success or false on failure.
See also: saprfc_export(), saprfc_import(), saprfc_server_export()

saprfc_server_import

(PHP 4, PHP 5)
saprfc_server_import  --  Get a value of a import parameter

Description

mixed saprfc_server_import (int fce, string name)
Return value of a import parameter name for function handle fce. See also: saprfc_import(), saprfc_export(), saprfc_server_export()

saprfc_server_dispatch

(PHP 4, PHP 5)
saprfc_server_dispatch  --  Receive a single RFC request and call a corresponding PHP function

Description

int saprfc_server_dispatch (int rfc, array list [, int timeout])
Function waits for incoming a rfc request (forever or period defined by timeout parameter in seconds), than calls a corresponding PHP function. PHP server functions are defined in array list, key is function name (upper case) and value is function handle. Return SAPRFC_OK on success, SAPRFC_RETRY on timeout expire, -1 if call PHP server function failed or other error code (see saprfc_call_and_reveive() ).

Example 1. Implementation of server PHP function RFC_READ_REPORT()

function RFC_READ_REPORT ($fce)
{ 
   $PROGRAM = saprfc_server_import ($fce,"PROGRAM");
   if ($PROGRAM =="") return ("EMPTY");  // raise exception EMPTY
   $list = file ($PROGRAM);
   saprfc_table_init ($fce,"QTAB");
   for ($i=0; $i
       saprfc_table_append ($fce,"QTAB",array ("LINE"=>$list[$i]));
   saprfc_server_export ($fce,"SYSTEM","PHP");     
   return;
}

$DEF_RFC_READ_REPORT = array (....) // see to saprfc_function_define() example

$GLOBAL_FCE_LIST[RFC_READ_REPORT] = saprfc_function_define (0,"RFC_READ_REPORT",$DEF_RFC_READ_REPORT);

$rfc = saprfc_server_accept ($argv);
$rfc_rc = saprfc_server_dispatch ($rfc,$GLOBAL_FCE_LIST);
?>
                 
See also: saprfc_function_define(), saprfc_server_accept(),

saprfc_server_register_check

(PHP 4, PHP 5)
saprfc_server_register_check  --  Check for registered RFC server at a SAP gateway

Description

array saprfc_server_register_check (string tpid, string gwhost, string gwservice)
An RFC program can use this call to check whether and how many RFC server programs are registered at a SAP gateway with a defined program ID (tpid). Values are returned in the array ("ntotal"=>?, "ninit"=>?,"nready"=>?,"nbusy"=>? ) 
An RFC server program which registers at a SAP gateway and then waits for RFC requests from any R/2 or R/3 or another external program can have one of the following 3 states:
INIT: RFC server is only registered at the SAP gateway, it doesn't wait at this moment for RFC request. An RFC server enters in this state after saprfc_server_accept() .
READY: RFC server enters in this state after saprfc_server_dispatch(), saprfc_trfc_dispatch() ; It is now ready to process incoming RFC requests.
BUSY: RFC server is processing an RFC request and is not available for other ones.
See also: saprfc_server_register_cancel()

saprfc_server_register_cancel

(PHP 4, PHP 5)
saprfc_server_register_cancel  --  Cancel all registered RFC servers at a SAP gateway

Description

array saprfc_server_register_cancel (string tpid, string gwhost, string gwservice)
An RFC program can use this call to cancel all registered RFC servers at a SAP gateway with a defined program ID (tpid). 
Pay attention that RFC servers in BUSY state cannot be canceled. In this case you will have a difference between the output parameters $array[ntotal] and $array[ncancel] returned by this call.
See also: saprfc_server_register_check()

saprfc_set_trace

(PHP 4, PHP 5)
saprfc_set_trace  --  Activate/Deactivate the RFC trace

Description

void saprfc_set_trace (int rfc, bool level)
Activates the RFC trace (level = true) for a specified connection (valid rfc handle) or for all RFC connections (rfc = 0).

saprfc_table_append

(PHP 4, PHP 5)
saprfc_table_append  --  Append a line at end of internal table

Description

bool saprfc_table_append (int fce, string name, array value)
Append a value at the end of an internal tablename.

saprfc_table_init

(PHP 4, PHP 5)
saprfc_table_init  --  Init a internal table

Description

bool saprfc_table_init (int fce, string name)
Deletes all rows from a table name.

saprfc_table_insert

(PHP 4, PHP 5)
saprfc_table_insert  --  Insert a line to an internal table

Description

bool saprfc_table_insert (int fce, string name, array value, int index)
Insert a value before line index in a table name.

saprfc_table_modify

(PHP 4, PHP 5)
saprfc_table_modify  --  Modify a line of an internal table

Description

bool saprfc_table_modify (int fce, string name, array value, int index)
Modify a line index of an internal table name with a value.

saprfc_table_read

(PHP 4, PHP 5)
saprfc_table_read  --  Read a line from an internal table

Description

array saprfc_table_read (int fce, string name, int index)
Read a value from an internal table name from line index (indexed from 1,2,...)

saprfc_table_remove

(PHP 4, PHP 5)
saprfc_table_remove  --  Remove a line of an internal table

Description

bool saprfc_table_remove(int fce, string name, int index)
Remove line index from a table name.

saprfc_table_rows

(PHP 4, PHP 5)
saprfc_table_rows  --  Get a number of lines an internal table

Description

int saprfc_table_rows (int fce, string name)
Get a number of lines an internal table name.

saprfc_trfc_call

(PHP 4, PHP 5)
saprfc_trfc_call  --  Calls a function module in R/3 indirectly (tRFC)

Description

int saprfc_trfc_call (int fce, string tid)
Calls a function module in R/3 indirectly. 
With this function, the call of a function module in R/3 will use the transactional RFC interface in R/3.
Export parameters are not supported. 
If an error occurs (almost only communication errors), the RFC client program has to reconnect to R/3 later and repeat this RFC call with the specific TransID. It must not create a new TransID via saprfc_trfc_tid()
See also: saprfc_call_and_receive(), saprfc_trfc_tid()

saprfc_trfc_dispatch

(PHP 4, PHP 5)
saprfc_trfc_dispatch  --  Receives a single RFC request and call a corresponding PHP function (tRFC)

Description

int saprfc_trfc_dispatch (int rfc, array list [, int timeout])
Alias to saprfc_server_dispatch().
See also: saprfc_server_dispatch()

saprfc_trfc_install

(PHP 4, PHP 5)
saprfc_trfc_dispatch  --  Installs functions to control transactional behaviour (tRFC)

Description

bool saprfc_trfc_install (string tid_check, string tid_commit, string tid_rollback, string tid_confirm, string dispatcher)
This function was introduced to allow an RFC server program to ensure exactly-once behaviour for functions being called via tRFC in ABAP: saprfc_trfc_install() must thus be called by RFC server program before thesaprfc_trfc_dispatch() loop is entered if this program wants to receive transactional RFC calls and must ensure that RFC calls are done excatly once. 
Without installing these functions it can only be guaranteed that an RFC function call issued by 'Call Function... In Background Task' is done at least once. Then all function modules offered by such a server program which are called via 'Call Function... In Background Task' must cope with being called more then once. 
If installed, the first function tid_check, if a transactional RFC is to be called. The actual Transaction ID is passed. The function has to store this transaction-ID in permanent storage and return 0. If the same function will be called later again with the same transaction-ID, it has to make sure that it will return a non-zero value. If the same transaction is already running by another process but is not completed, the function has to wait until the transaction completes. 
The second function tid_commit is called if all the RFC function module calls are done and the local transaction can be completed. It should be used to locally commit the transaction, if necessary . 
The third function tid_rollback is called instead of the second function, if, from the point of view of the RFC library, there occurred an error while processing the local transaction. This function can be used to roll back the local transaction. 
The fourth function tid_confirm will be called if the local transaction is completed also from the point of view of the calling system and all information on this transaction-ID can be discarded.
The last function dispatcher is called from saprfc_trfc_dispatch() and return function handle for function name.

See the trfcserv.php example.
See also: saprfc_trfc_dispatch()

saprfc_trfc_tid

(PHP 4, PHP 5)
saprfc_trfc_tid  --  Gets a transaction-ID for a following call of a function module using tRFC

Description

string saprfc_trfc_tid (int rfc)
Gets a transaction-ID for a following call of a function module in R/3 using the transactional RFC interface in R/3. With this function a new TransID will be produced from the R/3 System. The RFC client program has to call a function module in R/3 via saprfc_trfc_call() with this TransID. 
If an error occurs (e.g. communication error) during the call of a function module in R/3 via saprfc_trfc_call(), the RFC client program has to reconnect the RFC connection and repeat the saprfc_trfc_call() without creating a new TransId
See also: saprfc_trfc_call()

saprfc_open

(PHP 4, PHP 5)
saprfc_open  --  Open a RFC connection to SAP R/3

Description

int saprfc_open (array conn)
Open a RFC connection to an SAP R/3. Return RFC handle on success or false on failure. The connection parameters in array conn are:
        conn = array ("ASHOST" => "",          
                      "SYSNR" => "",           
                      "CLIENT" => "",          
                      "USER" => "",            
                      "PASSWD" => "",          
                      "GWHOST" =>"",     
                      "GWSERV" =>"",  
                      "MSHOST" =>"",            
                      "R3NAME" =>"",     
                      "GROUP" =>"",           
                      "LANG" =>"",           
                      "TRACE" =>"");             
          

Example 1. Login to aplication server

$rfc = saprfc_open (array ("ASHOST"=>"server","SYSNR"=>"20","CLIENT"=>"400",
                             "USER"=>"test", "PASSWD" =>"test"));
   
?>
                 

Example 2. Login to logon group (using load balancing)

$rfc = saprfc_open (array ("CLIENT"=>"400", "USER"=>"test", "PASSWD" =>"test", 
                             "MSHOST"=>"server1", "R3NAME"=>"DEV", "GROUP"=>"PUBLIC"));

?>
                 
Note: If you use load balancing, service sapms (where is system name) must be set in services file (/etc/services) on your PHP server.
See also: saprfc_error(), saprfc_close()

saprfc_optional

(PHP 4, PHP 5)
saprfc_optional  --  Set a import parameter as optional

Description

bool saprfc_optional (int fce, string name, bool value)
Set/reset import parameter name as optional (1/0). Return true on success or false on failure. If the parameter is set as optional and has no value assigned, the default value of parameter is used (see to interface definition in transaction SE37).

saprfc_set_code_page

(PHP 4, PHP 5)
saprfc_set_code_page  --  Set SAP codepage for a RFC connection

Description

bool saprfc_set_code_page (int rfc, string codepage)
Set SAP codepage for a RFC connection rfc.

saprfc_allow_start_program

(PHP 4, PHP 5)
saprfc_allow_start_program  --  Explicitly allows the RFC library to start the programs

Description

bool saprfc_allow_start_program ([ string program_list ])
Explicitly allows the RFC library to start the programs described in the list as input parameter program_list if this is required by the RFC partner. The program_list is a colon (;) separated list of programs that can be called from the rfc stack. If the function is called without any parameter, all programs can be called from the rfc stack. 

This call can be used either in RFC client or RFC server program.

It can be useful if you have a document management system within R/3 and want to check out documents (from sap) or check in documents (to sap) with the help of the external programs sapftp/saphttp (very comfortable; ftp/http-clients that can be controlled from external here from the sap stack; can be downloaded from the SAP Service Marketplace). The call of saprfc_allow_start_program() is needed for BAPIs like BAPI_DOCUMENT_CHECKOUTMODIFY2 or BAPI_DOCUMENT_CHECKIN2 and the like. 

Example 1: Allow start external program sapftp and saphttp

$rc = saprfc_allow_start_program ("sapftp;saphttp");
                 


Example 2: Allow start any external program

$rc = saprfc_allow_start_program ();
                 

saprfc_get_ticket

(PHP 4, PHP 5)
saprfc_get_ticket  --  Retrieve backend generated cookie version 2 after calling saprfc_open with flag GETSSO2

Description

string saprfc_get_ticket ( int rfc)
Return SSO2 ticket or false if ticket is not available. 

Example 1: Get SSO2 logon ticket

$login = array (
                   "ASHOST"=>"hostname",
                   "SYSNR"=>"00",
                   "CLIENT"=>"client",
                   "USER"=>"username",
                   "PASSWD"=>"password",
                   "GETSSO2"=>"1");
             $rfc = saprfc_open ($login );
             $ticket = saprfc_get_ticket($rfc);
                 


Example 2: Login with SSO2 ticket

$login = array ( 
                  "ASHOST"=>"hostname",
                  "SYSNR"=>"00",
                  "CLIENT"=>"client",
                  "MYSAPSSO2"=>$ticket);
             $rfc = saprfc_open ($login );