Are you unable to modify another user’s PHP file on the IBM i? Do you constantly need to give QTMHHTTP read permissions to the new PHP you uploaded? After going through this guide you’ll fix these issues and streamline your PHP development on the IBM i while maintaining security of the IFS.

Overview of permissions on your Webroot folder for Zend Server:
*PUBLIC: DTAAUT ( *NONE)
PRIMARY GROUP: NOGROUP = DTAAUT (*RX)
OWNER: WEBCODERS= DTAAUT (*RWX)

Summary: Public gets no access, Primary Group is a group that the user QTMHHTTP is a part of and only has read access, and the owner is your development team group profile (WEBCODERS) with your web development team user profiles in that group.

As always test this on a development machine DON’T DO THIS IN PRODUCTION unless you’ve tested it

5 Steps to secure your PHP installation

1. Don’t give *PUBLIC access

[sourcecode language=”SQL”]
CHGAUT OBJ(‘/www/zendsvr/htdocs/’) USER(*PUBLIC) DTAAUT(*NONE) OBJAUT(*NONE) SUBTREE(*ALL)
[/sourcecode]
I’ve heard many people who are insecurely using PHP on the IBM i. If you are giving *PUBLIC any access to your files under /www/zendsvr/htdocs you are giving too much access. You don’t want anyone with access to your IBM I to read your PHP files or your configuration files with database username and password. You should make sure *PUBLIC has no data authorities on all files under web root directory using the CHGAUT command recursively.

2. Set the Primary Group on the webroot (/www/zendsvr/htdocs) to a group with QTMHHTTP in it

[sourcecode language=”SQL”]
CHGPGP OBJ(‘/www/zendsvr/htdocs’) NEWPGP(NOGROUP) RVKOLDAUT(*NO) SUBTREE(*ALL)
CHGAUT OBJ(‘/www/zendsvr/htdocs/’) USER(NOGROUP) DTAAUT(*RX) OBJAUT(*NONE) SUBTREE(*ALL)
[/sourcecode]
Remember that each new object under a parent directory inherits the *PUBLIC authority, primary group authority and the owner authority of the parent. So you’ll want to set the primary group to NOGROUP and give it Read access. Make sure QTMHHTTP is a user of this group. This is the user that PHP is using to access the files and is typically called APACHE or NOBODY in linux systems.

3. Give access to a development team group profile so your web developers have write access to create new files and directories and read access to view the files on the server.  Unfortunately you’ll always have to re-run CHGAUT for WEBCODERS as when someone uploads a file they become the owner.  You may want to consider a daily job that automatically runs this or have your developers share the login information for WEBCODERS and always upload with that profile. 

[sourcecode language=”SQL”]
CHGOWN OBJ(‘/www/zendsvr/htdocs/’) NEWOWN(WEBCODERS) RVKOLDAUT(*NO) SUBTREE(*ALL)
CHGAUT OBJ(‘/www/zendsvr/htdocs/’) USER(WEBCODERS) DTAAUT(*RWX) OBJAUT(*ALL) SUBTREE(*ALL)
[/sourcecode]

4. Give write permissions to directories that QTMHHTTP needs write access.  If your PHP is saving a file or creating a file to the IFS it will need write permissions to that directory. 

[sourcecode language=”SQL”]
CHGAUT OBJ(‘/www/zendsvr/writeable/uploads’) USER(QTMHHTTP) DTAAUT(*RWX) OBJAUT(*NONE) SUBTREE(*NO)[/sourcecode]

Below are some shell functions you can use if you have bash or bourne shell

#Parameter ${1} is the directory you want to effect like /www/zendsvr/htdocs/ or /www/zendsvr/writeable/uploads
function http-permissions() {
system -i "CHGAUT OBJ('${1}') USER(NOGROUP) DTAAUT(*RX) OBJAUT(*NONE) SUBTREE(*ALL)"
system -i "CHGPGP OBJ('${1}') NEWPGP(NOGROUP) RVKOLDAUT(*NO) SUBTREE(*ALL)"
#Usage: on the command line
#http-permissions /www/zendsvr/htdocs/
#/www/zendsvr/htdocs/ will be given permissions recursively to the apache group
}
function http-write-permissions() {
system -i "CHGAUT OBJ('${1}') USER(QTMHHTTP) DTAAUT(*RWX) OBJAUT(*NONE) SUBTREE(*NO)"
}
function remove-public-permissions() {
system -i "CHGAUT OBJ('${1}') USER(*PUBLIC) DTAAUT(*NONE) OBJAUT(*NONE) SUBTREE(*ALL)"
#in case someone incorrectly gave public permissions
}
function developer-permissions() {
system -i "CHGOWN OBJ('${1}') NEWOWN(WEBCODERS) RVKOLDAUT(*NO) SUBTREE(*ALL)"
system -i "CHGAUT OBJ('${1}') USER(WEBCODERS) DTAAUT(*RWX) OBJAUT(*ALL) SUBTREE(*ALL)"
}

view raw
.functions.sh
hosted with ❤ by GitHub

5. (Optional) Set the umask to set the default permissions given to new files created by a program (like FTP, SFTP, SSH).  In the example below the first 0 means give user rwx, 2 means give group rx, and 7 means give other nothing.

umask 027
#u=rwx,g=rx,o=

For SFTP you’d modify sshd_config to load a shell .profile that would then run the umask.  (replace * with the version number of openssh you’re using or find it by running find)

find / | grep sshd_config
vi /QOpenSys/QIBM/UserData/SC1/OpenSSH/openssh-*.*p*/etc/sshd_config
# set ibmpaseforishell to your favorite shell (in this case bash)
ibmpaseforishell=/QOpenSys/opt/freeware/bin/bash
#set the umask in our .profile so it will always load by using this command to append 
umask 022 to the end of the file (.profile).
echo "umask 022" >> ~/.profile

#shout out to @aaronbartell for informing me of umask

Experiment using Authorization List: 

Now I looked into using Authorization lists but they don’t inherit from the parent directory IF you’re using the mkdir command API (different from ibm i command line mkdir alias).  That would be the best case scenario since then new objects would get the WEBDEVAUTL authorization list inherited and your development team would be in that list and everyone on your team could create new files and directories and everyone else could modify them later.  Below are the commands to create a AUTL, but remember it will only work if your NOT using the mkdir command

CRTAUTL AUTL(WEBDEVAUTL) TEXT(‘Auth List for Web Developers’)
ADDAUTLE AUTL(WEBDEVAUTL) USER(WEBDEV1 WEBDEV2) AUT(*ALL)
CHGAUT OBJ(‘/www/zendsvr/htdocs/’) AUTL(WEBDEVAUTL) DTAAUT(*RWX) OBJAUT(*ALL) SUBTREE(*ALL)

More info on Mkdir not inheriting from the parent directory here: https://www.ibm.com/developerworks/community/forums/html/topic?id=77777777-0000-0000-0000-000014510624 .  Hopefully IBM will one day have mkdir have the same functionality as CRTDIR CL command.  Another good read about the IFS: http://publib.boulder.ibm.com/iseries/v5r1/ic2924/books/c415300522.htm