20110911

Blind Administration

A few weeks ago I've lost the ability to see any output form my MacBook Pro.

It was a second time. For the first time I had lost the embedded led display only.
The DVI output worked fine. Then came the healing power of promise - I have to buy a new one.
But threat without the coverage it's just the bucket of words.
The MBP makes me blind completely and definately. No video output. No remote access.
No working ssh daemon, no firewall access, no future.

I thought the target mode would be the cure.
I have PowerBook Pismo with Tiger onboard. Unfortunately, the data on MBP was encrypted with
a FileVault from Snow Leopard. Either try of target mode connection, or try of manual mount failed.

Collecting of the recipe components took me many hours, often filled with an exasperation.
Hidden typos. Invisible prompts. Lurking daemons.

The recipe.
It's here to remember. It's here to save other souls.

Power On.
Listen to chime and wait a few moments, then log in yourself:
username TAB
password

Open Applications
⌘+Shift+A
and invoke your favourite text terminal by typing its name, followed by CMD+O
i t e r m ⌘+O

Confirm you're in:
$ say ok
$ sudo su
> put your password <
Confirm your personality.
$ whoami | say
Let the dogs out. Select a race, choose wisely.
$ launchctl load -w /System/Library/LaunchDaemons/telnet.plist # enable configuration and
$ launchctl load -w /System/Library/LaunchDaemons/ssh.plist    # set Disable key to false
$ launchctl start com.apple.telnetd
$ launchctl start com.openssh.sshd
Check the locks.
$ defaults read /Library/Preferences/com.apple.alf globalstate | say
2
Firewall states
  • 0 - de-activated
  • 1 - on for specific services
  • 2 - on for essential services
Open the gates.
Pretty enough for older systems (Tiger), where no reboot required:
$ ipfw flush
> 'y' to flush <
$ ipfw list | say # 'any to any' means success
Permanent solution:
$ defaults write /Library/Preferences/com.apple.alf globalstate -int 0
$ reboot
Connect and enjoy it.

Mount USB Disk drive.
sh-3.2# diskutil list| grep SAM
   1:             Windows_FAT_32 SAMSUNG                 2.0 TB     disk2s1
sh-3.2# diskutil mountDisk SAMSUNG
Volume(s) mounted successfully
Rsync your secrets.

20110103

db2setup start failure on Debian/Ubuntu

Two late evenings of life - that was the time cost of the solution discovery.
I had tried to put the DB2 Express-C 9.7.2 on 64-bit Linux system, and I failed either on Ubuntu 8.04 LTS
or on Debian 5.0 (I know it is not recommended/supported solution).

The first and the last problem was related to the db2setup startup error.
It can be seen from the console just like that:

# ./db2setup
DBI1190I db2setup is preparing the DB2 Setup wizard which will guide
you through the program setup process. Please wait.


#

But, there was the trail in the error log:

# cd /tmp
# cat db2setup.err
Exception in thread "main" java.lang.UnsatisfiedLinkError: awt (An exception was pending after running JNI_OnLoad)
at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:998)
at java.lang.ClassLoader.loadLibraryWithClassLoader(ClassLoader.java:962)
at java.lang.System.loadLibrary(System.java:465)
at sun.security.action.LoadLibraryAction.run(LoadLibraryAction.java:69)
at java.security.AccessController.doPrivileged(AccessController.java:202)
at java.awt.Toolkit.loadLibraries(Toolkit.java:1605)
at java.awt.Toolkit.(Toolkit.java:1627)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:200)
at java.awt.AWTEvent.(AWTEvent.java:220)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:200)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:167)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:167)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:167)
at sun.misc.Unsafe.ensureClassInitialized(Native Method)
at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:37)
at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:122)
at java.lang.reflect.Field.acquireFieldAccessor(Field.java:920)
at java.lang.reflect.Field.getFieldAccessor(Field.java:901)
at java.lang.reflect.Field.get(Field.java:360)
at com.ibm.db2.tools.common.support.AssistManager.loadVKeys(Unknown Source)
at com.ibm.db2.tools.common.support.AssistManager.(Unknown Source)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:200)
at DB2Setup.(Unknown Source)
at DB2Setup.main(Unknown Source)
#

Let me start from the beginning.

# ./db2setup
WARNING:
Can't use string to find the version of libstdc++.
Check the following web site for the up-to-date system requirements
of IBM DB2 9.7
http://www.ibm.com/software/data/db2/udb/sysreqs.html
http://www.software.ibm.com/data/db2/linux/validate
The force option "-f sysreq" is used to force the installation ...

DBI1190I db2setup is preparing the DB2 Setup wizard which will guide
you through the program setup process. Please wait.



The DISPLAY variable is not set properly. Ensure that the DISPLAY variable is set properly and that permissions are set properly to open windows on the display specified, then rerun the command.
#

Even with the -f sysreq there was no visible progress.
Before the installation begins I have installed the libaio1 and libstdc++6 as it was mentioned in the online documentation.

The installation was on the remote server, so to verify that X11 session forwarding works fine I had to install xauth and use the ssh -Y option.

# xauth list
digestive.deadsystems.com/unix:10 MIT-MAGIC-COOKIE-1 a957c95c1c862f5314b32e88c5bd9e17
# echo $DISPLAY
localhost:10.0

I have used the xarclock to check that the remote app is being displayed fine on my laptop.

"Can't use string to find the version of libstdc++." -
it was resolved by simple binutils package installation (to get the strings binary).

But, there was no progress yet.

# ./db2setup
WARNING:
The 32 bit library file libstdc++.so.6 is not found on the system.
32-bit applications may be affected.
DBI1190I db2setup is preparing the DB2 Setup wizard which will guide
you through the program setup process. Please wait.


#

Then I thought that the /tmp/db2setup.err contains the java related exception, but there is no java vm on the machine.

# java -version
-ksh93: java: not found [No such file or directory]

After the sun-java6-jre installation there was still nothing more.

# java -version
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03, mixed mode)


A few search queries more and I have found a tip:

GUI applications, such as the JConsole monitoring tool, on 64-bit Ubuntu with a 32-bit JVM
When running a 32-bit JVM on a 64-bit Ubuntu system, GUI applications do not start because some AWT libraries are missing. To fix the problem, install the 32-bit libraries using the ia32-libs package:
sudo apt-get install ia32-libs
The following exception is thrown if the libraries are not available:
Exception in thread "main" java.lang.UnsatisfiedLinkError: awt (An exception was pending after running JNI_OnLoad)
at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:993)
at java.lang.ClassLoader.loadLibraryWithClassLoader(ClassLoader.java:962)
at java.lang.System.loadLibrary(System.java:465)
... lines removed for clarity ...
If problems are encountered with DNS name resolution, install the package lib32nss-mdns.

But neither ia32-libs nor lib32nss-mdns installation helped me to go further.
The only benefit was the lack of warning message:

WARNING:
The 32 bit library file libstdc++.so.6 is not found on the system.
32-bit applications may be affected.

Then It looked like:

# ./db2setup
DBI1190I db2setup is preparing the DB2 Setup wizard which will guide
you through the program setup process. Please wait.


#

After the additional few hours of digging through the differences between the library sets on two machines,
on which the first have the fully operational DB2 instances and the second is the reported unlucky node, I have pointed the main responsible for all the evil - there was no libxft2. After the apt-get install libxft2 - db2setup has raised from the ashes.

Enjoy.

20110101

Un-monit

Using the monit to look after the hosts and services, sometimes you need to stop watching a particular check.
The argument for unmonitor option is the process name or host name being monitored, ex.

# monit status
[...]
Remote Host 'eye0.deadsystems.com'
status Connection failed
monitoring status monitored
[...]

# monit unmonitor eye0.deadsystems.com
# monit summary
[...]
Process 'sshd' running
Remote Host 'eye0.deadsystems.com' not monitored
[...]

20100928

User passwords may not be provided in pre-encoded form

One of the very first differences between the OpenDS and DSEE I have noticed
was the possibility of ldapmodifing the userPassword value. In OpenDS this feature is disabled by default.


$ ldapmodify -p 1389 -D cn=dirmgr -j ~/.odspwd
dn: cn=odsmgr,cn=Root DNs,cn=config
changetype: modify
replace: userpassword
userpassword: {SSHA512}1g9Byn7MOZ1TgZCNY8gw4NA6o8UguyYg0b48d89zJS+AyIs9OP2rHfbZ6aaqTluryTh3Ux1ZW5RSWuTjH9wvtBxFXCxJzyt0

Processing MODIFY request for cn=odsmgr,cn=Root DNs,cn=config
MODIFY operation failed
Result Code: 53 (Unwilling to Perform)
Additional Information: User passwords may not be provided in pre-encoded form

$ ldapsearch -p 1389 -D cn=dirmgr -j ~/.odspwd -b cn=config "cn=Default Password Policy" ds-cfg-allow-pre-encoded-passwords
dn: cn=Default Password Policy,cn=Password Policies,cn=config
ds-cfg-allow-pre-encoded-passwords: false

$ ldapsearch -p 1389 -D cn=dirmgr -j ~/.odspwd -b cn=config "cn=Root Password Policy" ds-cfg-allow-pre-encoded-passwords
dn: cn=Root Password Policy,cn=Password Policies,cn=config
ds-cfg-allow-pre-encoded-passwords: false


I do not know the pro and con voices in this discussion, but for me there is only one disadvantage - the ability to observe
multiple instances of the same encoded password strings. And it is only the risk when the one who would notice this fact is the bad guy.
In contrast I see only the advantages.
So...

dn: cn=Root Password Policy,cn=Password Policies,cn=config
changetype: modify
replace: ds-cfg-allow-pre-encoded-passwords
ds-cfg-allow-pre-encoded-passwords: true

LDIF has been implemented.

$ encode-password -s SSHA512 -f ~/.odspwd
Encoded Password: "{SSHA512}Gur7YkCGk4oP2sun+KqpXF4rB9wmzUgjhb3P6hBNmNRLBBQgTxSwLR5WuO41yytG9sUzslYc2HyUAM1otujRW+UkAOapbB7c"

$ ldapmodify -p 1389 -D cn=dirmgr -j ~/.odspwd
dn: cn=odsmgr,cn=Root DNs,cn=config
changetype: modify
replace: userpassword
userpassword: {SSHA512}Gur7YkCGk4oP2sun+KqpXF4rB9wmzUgjhb3P6hBNmNRLBBQgTxSwLR5WuO41yytG9sUzslYc2HyUAM1otujRW+UkAOapbB7c

Processing MODIFY request for cn=odsmgr,cn=Root DNs,cn=config
MODIFY operation successful for DN cn=odsmgr,cn=Root DNs,cn=config

$ ldapsearch -p 1389 -D cn=dsmgr -j ~/.dspwd -b cn=config "cn=odsmgr" +
The simple bind attempt failed
Result Code: 49 (Invalid Credentials)
$ ldapsearch -p 1389 -D cn=dsmgr -j ~/.odspwd -b cn=config "cn=odsmgr" +
dn: cn=odsmgr,cn=Root DNs,cn=config
modifiersName: cn=Directory Manager,cn=Root DNs,cn=config
modifyTimestamp: 20100927104857Z
createTimestamp: 20100924124513Z
pwdChangedTime: 20100927104857.435Z
creatorsName: cn=Directory Manager,cn=Root DNs,cn=config
entryDN: cn=odsmgr,cn=root dns,cn=config
entryUUID: 99296ddd-e705-468b-8112-afd19bb38821
hasSubordinates: false
subschemaSubentry: cn=schema
ds-pwp-password-policy-dn: cn=Root Password Policy,cn=Password Policies,cn=confi
g
structuralObjectClass: inetOrgPerson
numSubordinates: 0

20100926

Directory Managers. Lots of Directory Managers.

Last week I have decided to take some OpenDS practise. The practical solving of a problem is better
then hundreds lines of reading about the others activity. At least that's the way I feel.
Task: Multiple the Directory Manager account to delegate administration without providing your secret password.

In theory it is possible without any problems.
The only requirement is the object class of ds-cfg-root-dn-user.
I have copied almost the all attributes from the current "root" account into a new one.

$ ldapsearch -p 1389 -D cn=dirmgr -j ~/.odspwd -b cn=config "cn=Directory Manager"
dn: cn=Directory Manager,cn=Root DNs,cn=config
sn: Manager
ds-cfg-alternate-bind-dn: cn=dirmgr
cn: Directory Manager
givenName: Directory
objectClass: ds-cfg-root-dn-user
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
userpassword: {SSHA512}1g9Byn7MOZ1TgZCNY8gw4NA6o8UguyYg0b48d89zJS+AyIs9OP2rHfbZ6
aaqTluryTh3Ux1ZW5RSWuTjH9wvtBxFXCxJzyt0


$ ldapmodify -p 1389 -D cn=dirmgr -j ~/.odspwd
dn: cn=odsmgr,cn=Root DNs,cn=config
changetype: add
objectClass: ds-cfg-root-dn-user
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
cn: odsmgr
givenName: ODS
sn: Manager
userPAssword: secret

Processing ADD request for cn=odsmgr,cn=Root DNs,cn=config
ADD operation successful for DN cn=odsmgr,cn=Root DNs,cn=config

For the initial testing I have duplicated also the password.

$ ldappasswordmodify -p 1389 -D "cn=dirmgr" -j ~/.odspwd \
> -a "dn:cn=odsmgr,cn=Root DNs,cn=config" -c secret -N ~/.odspwd
The LDAP password modify operation was successful


During the cut'n'copy session of ldapmodify I have omitted ds-cfg-alternate-bind-dn intentionally.
I thought the adjective "alternate" is self-explanatory.
Wrong!

$ ldapsearch -p 1389 -D cn=odsmgr -j ~/.odspwd -b cn=config cn=odsmgr
The simple bind attempt failed
Result Code: 49 (Invalid Credentials)

$ ldapmodify -p 1389 -D "cn=dirmgr" -j ~/.odspwd
dn: cn=odsmgr,cn=Root DNs,cn=config
changetype: modify
add: ds-cfg-alternate-bind-dn
ds-cfg-alternate-bind-dn: cn=odsmgr

Processing MODIFY request for cn=odsmgr,cn=Root DNs,cn=config
MODIFY operation successful for DN cn=odsmgr,cn=Root DNs,cn=config

$ ldapsearch -p 1389 -D cn=odsmgr -j ~/.odspwd -b cn=config cn=odsmgr
dn: cn=odsmgr,cn=Root DNs,cn=config
sn: Manager
ds-cfg-alternate-bind-dn: cn=odsmgr
cn: odsmgr
givenName: ODS
objectClass: top
objectClass: ds-cfg-root-dn-user
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: person
userPassword: {SSHA}gF7nQ6N6gmpuufM1/8FemlwH1/HikScaVOlP3Q==

Why not to test a case with multiple ds-cfg-alternate-bind-dn attibute values.

$ ldapmodify -p 1389 -D "cn=dirmgr" -j ~/.odspwd
dn: cn=odsmgr,cn=Root DNs,cn=config
changetype: modify
add: ds-cfg-alternate-bind-dn
ds-cfg-alternate-bind-dn: cn=dsmgr

Processing MODIFY request for cn=odsmgr,cn=Root DNs,cn=config
MODIFY operation successful for DN cn=odsmgr,cn=Root DNs,cn=config

$ ldapsearch -p 1389 -D cn=dsmgr -j ~/.odspwd -b cn=config cn=odsmgr
dn: cn=odsmgr,cn=Root DNs,cn=config
ds-cfg-alternate-bind-dn: cn=odsmgr
ds-cfg-alternate-bind-dn: cn=dsmgr
sn: Manager
cn: odsmgr
givenName: ODS
objectClass: ds-cfg-root-dn-user
objectClass: top
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
userPassword: {SSHA}gF7nQ6N6gmpuufM1/8FemlwH1/HikScaVOlP3Q==

But wait a minute. Why the userPassword value is encoded with a SSHA password scheme, while
the Directory Manager and the default root scheme is pointing to SSHA512.

$ ldapsearch -p 1389 -D cn=dsmgr -j ~/.odspwd -b cn=config cn="Directory Manager" userpassword
dn: cn=Directory Manager,cn=Root DNs,cn=config
userpassword: {SSHA512}1g9Byn7MOZ1TgZCNY8gw4NA6o8UguyYg0b48d89zJS+AyIs9OP2rHfbZ6
aaqTluryTh3Ux1ZW5RSWuTjH9wvtBxFXCxJzyt0

$ ldapsearch -p 1389 -D cn=dsmgr -j ~/.dspwd -b cn=config "cn=Root Password Policy" \
> ds-cfg-default-password-storage-scheme
dn: cn=Root Password Policy,cn=Password Policies,cn=config
ds-cfg-default-password-storage-scheme: cn=Salted SHA-512,cn=Password Storage Sc
hemes,cn=config

The answer has come with the hint from Ludovic Poitou.
The virtual attribute of ds-pwp-password-policy-dn should be set explicitly.

$ ldapmodify -p 1389 -D cn=dsmgr -j ~/.odspwd
dn: cn=odsmgr,cn=Root DNs,cn=config
changetype: modify
add: ds-pwp-password-policy-dn
ds-pwp-password-policy-dn: cn=Root Password Policy,cn=Password Policies,cn=config

Processing MODIFY request for cn=odsmgr,cn=Root DNs,cn=config
MODIFY operation successful for DN cn=odsmgr,cn=Root DNs,cn=config

$ openssl rand -base64 12 > ~/.dspwd

$ ldappasswordmodify -p 1389 -D cn=dsmgr -j ~/.odspwd -a "cn=odsmgr,cn=Root DNs,cn=config" \
> -C ~/.odspwd -N ~/.dspwd
The LDAP password modify operation was successful

$ ldapsearch -p 1389 -D cn=dsmgr -j ~/.dspwd -b cn=config cn=odsmgr userpassword
dn: cn=odsmgr,cn=Root DNs,cn=config
userpassword: {SSHA512}BxvZzrhuVpwOv6FMc9sI1infjPC7PQ0dXXdry4ZLNgq6FJbjCVfSiLwBO
A1uzaXAscS7pkNbfkP4hG11L9DTPsRfpusta+4x

Nice.

20100921

Custom Service Packages

During each subsequent comms implementation I forget one or more steps from the following recipe.
So, here comes the milestones to remember.
For the complete documentation refer to the wikis.sun.com.

Template for basic set of packages - da.cos.skeleton.ldif can be found in directory:
/opt/sun/comms/da/lib/config-templates/
on Delegated Administrator default installation path.

Usually I use only the packages for MailUser, MailCalendarUser and MailGroup.
After the customization the file might look like:

dn: cn=wisniosMailUser,o=mailuser,o=cosTemplates,o=root
changetype: add
objectclass: top
objectclass: LDAPsubentry
objectclass: extensibleobject
objectclass: cosTemplate
cn: wisniosMailUser
mailMsgMaxBlocks: 5000
mailAllowedServiceAccess: +imap,imaps,pop,pops,smtp,smtps,http,smime:ALL
daServiceType: mail user

dn: cn=wisniosMailCalendarUser,o=mailcalendaruser,o=cosTemplates,o=root
changetype: add
objectclass: top
objectclass: LDAPsubentry
objectclass: extensibleobject
objectclass: cosTemplate
cn: wisniosMailCalendarUser
mailMsgMaxBlocks: 5000
mailAllowedServiceAccess: +imap,imaps,pop,pops,smtp,smtps,http,smime:ALL
daServiceType: calendar user
daServiceType: mail user

dn: cn=wisniosMailGroup,o=mailgroup,o=cosTemplates,o=root
changetype: add
objectclass: top
objectclass: LDAPsubentry
objectclass: extensibleobject
objectclass: cosTemplate
cn: wisniosMailGroup
mailMsgMaxBlocks: 5000
daServiceType: mail group


Dry run:

# ldapmodify -p 1389 -D cn=dirmgr -j /root/.dspwd -n -f da.cos.wisnios.ldif
!adding new entry cn=wisniosMailUser,o=mailuser,o=cosTemplates,o=root

!adding new entry cn=wisniosMailCalendarUser,o=mailcalendaruser,o=cosTemplates,o=root

!adding new entry cn=wisniosMailGroup,o=mailgroup,o=cosTemplates,o=root

Wet run:

# ldapmodify -p 1389 -D cn=dirmgr -j /root/.dspwd -f da.cos.wisnios.ldif
adding new entry cn=wisniosMailUser,o=mailuser,o=cosTemplates,o=root

adding new entry cn=wisniosMailCalendarUser,o=mailcalendaruser,o=cosTemplates,o=root

adding new entry cn=wisniosMailGroup,o=mailgroup,o=cosTemplates,o=root

Check:

# ldapsearch -p 1389 -D cn=dirmgr -j /root/.dspwd -b o=cosTemplates,o=root \
> "(&(cn=wisnios*)(objectclass=LDAPsubentry))" daServiceType
version: 1
dn: cn=wisniosMailUser,o=mailuser,o=cosTemplates,o=root
daServiceType: mail user

dn: cn=wisniosMailCalendarUser,o=mailcalendaruser,o=cosTemplates,o=root
daServiceType: calendar user
daServiceType: mail user

dn: cn=wisniosMailGroup,o=mailgroup,o=cosTemplates,o=root
daServiceType: mail group

To make sure that the changes (packages) will be visible restart the app/web container.

20100908

How to automate the SpamAssassin feeding

This post is my answer to the Sun Wikis' entry about Enabling Anti-Spam functionality in Convergence.

Technologies used:
Messaging Server
SpamAssassin
RBAC - execution profiles

Messaging Server use the two variables to hold the email accounts for feeding anti-spam system
with the positive and false positive spam messages:

  • service.feedback.spam

  • service.feedback.notspam


But there is no embedded mechanism to deal with them.
Here comes my solution.

Every time the Convergence user marks the spam (ot not spam), with the appropriate button from its interface,
the mail is being sent to the address provided within the configuration.
The email messages accumulate in the accounts and waiting for the action.

Scenario:

  • fetching messages from spam account

  • teaching spamassassin with spam

  • cleaing INBOX folder

  • fetching messages from notspam account

  • teaching SA with ham

  • cleaning account



Methods:

  • fetching messages from spam account


    1. imsexport


  • teaching spamassassin with spam


    1. sa-learn --spam


  • cleaing INBOX folder


    1. mboxutil -d

    2. mboxutil -c


  • fetching messages from notspam account


    1. imsexport


  • teaching SA with ham


    1. sa-learn --ham


  • cleaning account


    1. mboxutil -d

    2. mboxutil -c



Due to a fact the script will be invoked by root account, to get the access either to imsexport files or sa-learn with valid Bayes DB,
I have decided to use one of the Solaris RBAC mechanisms - profiles.

I would not describe the profile creation step-by-step, because the learning by example is much more valuable.

# /usr/sadm/bin/smexec add -H localhost -u root -- \
-n "SpamAssassin Administration" -t cmd -c /export/home/sa/bin/sa-learn -U 105 -G 102
Authenticating as user: root

Type /? for help, pressing accepts the default denoted by [ ]
Please enter a string value for: password ::
There is no Solaris Management Console Server running on localhost.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
\
# svcadm enable wbem

# /usr/sadm/bin/smexec add -H localhost -u root -- \
-n "SpamAssassin Administration" -t cmd -c /export/home/sa/bin/sa-learn -U 105 -G 102
Authenticating as user: root

Type /? for help, pressing accepts the default denoted by [ ]
Please enter a string value for: password ::
Loading Tool: com.sun.admin.usermgr.cli.execs.UserMgrExecCli from localhost
Login to localhost as user root was successful.
Download of com.sun.admin.usermgr.cli.execs.UserMgrExecCli from localhost was successful.
You have entered a non-existent right SpamAssassin Administration.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
\
# cd /usr/lib/help/profiles/locale/C
# cat RtSAAdmin.html
< HTML >
< HEAD >
< TITLE >< /TITLE >
< /HEAD >
< BODY >
SpamAssassin Administration right allows the user or role SA management.
< /BODY >
< /HTML >

^^^^^
Spaces has been added to HTML tags in due to blogspot problems with handling this kind of stuff within the post body.

# /usr/sadm/bin/smprofile add -H localhost -u root -- \
-n "SpamAssassin Administration" -d "Manage SpamAssassin" -m RtSAAdmin.html
Authenticating as user: root

Type /? for help, pressing accepts the default denoted by [ ]
Please enter a string value for: password ::
Loading Tool: com.sun.admin.usermgr.cli.profile.UserMgrProfCli from localhost
Login to localhost as user root was successful.
Download of com.sun.admin.usermgr.cli.profile.UserMgrProfCli from localhost was successful.

# tail -1 /etc/security/prof_attr
SpamAssassin Administration:::Manage SpamAssassin:help=RtSAAdmin.html

# /usr/sadm/bin/smexec add -H localhost -u root -- \
-n "SpamAssassin Administration" -t cmd -c /export/home/sa/bin/sa-learn -U 105 -G 102
Authenticating as user: root

Type /? for help, pressing accepts the default denoted by [ ]
Please enter a string value for: password ::
Loading Tool: com.sun.admin.usermgr.cli.execs.UserMgrExecCli from localhost
Login to localhost as user root was successful.
Download of com.sun.admin.usermgr.cli.execs.UserMgrExecCli from localhost was successful.

# tail -1 /etc/security/exec_attr
SpamAssassin Administration:solaris:cmd:::/export/home/sa/bin/sa-learn:uid=105;gid=102


So, running sa-learn by the user / role with "SpamAssassin Administration" profile assigned
allow access to bayes DB files with the proper rights.
Examples can be seen in the script code provided below.


#!/usr/bin/ksh
#------------------------------------
# sa-feed.ksh
# feed SpamAssassin with {NOT}SPAM
# from file in mbox format
#====================================
# author: Marcin Wisnios
# e-mail: wisnios at wisnios dot com
#------------------------------------
PATH=$PATH:/opt/sun/comms/messaging64/bin:/export/home/sa/bin

TDIR=$(mktemp -td) # temporary directory
FILE=$TDIR/INBOX # mbox file
MUSR=$(ps -o user -p $(pgrep -nf dispatcher) | tail -1) # messaging server runtime user
SUSR=$(ps -o user -p $(pgrep -nf spamd) | tail -1) # spamassassin runtime user
SPAM=$(configutil -o service.feedback.spam) # feedback account for spam
NOTSPAM=$(configutil -o service.feedback.notspam) # feedback account for not spam
BDBL=/export/home/sa/.spamassassin # Bayes DB location
SALEARN="pfexec sa-learn --dbpath $BDBL" # fixed part of sa-learn invocation

chown $MUSR $TDIR
chmod 0755 $TDIR

imsexport -s INBOX -d $TDIR -u $SPAM


[ -f $FILE ] && {
chown $SUSR $FILE

NSPAM_BEFORE=$($SALEARN --dump magic 2> /dev/null | grep nspam | awk '{print $3}')
$SALEARN --mbox --spam $FILE 2> /dev/null &&\
NSPAM_AFTER=$($SALEARN --dump magic 2> /dev/null | grep nspam | awk '{print $3}')

[ $NSPAM_BEFORE -lt $NSPAM_AFTER ] && {
mboxutil -d user/$SPAM/INBOX
mboxutil -c user/$SPAM/INBOX
}

rm $FILE
}

imsexport -s INBOX -d $TDIR -u $NOTSPAM

[ -f $FILE ] && {
chown $SUSR $FILE

NHAM_BEFORE=$($SALEARN --dump magic 2> /dev/null | grep nham | awk '{print $3}')
$SALEARN --mbox --ham $FILE 2> /dev/null &&\
NHAM_AFTER=$($SALEARN --dump magic 2> /dev/null | grep nham | awk '{print $3}')

[ $NHAM_BEFORE -lt $NHAM_AFTER ] && {
mboxutil -d user/$NOTSPAM/INBOX
mboxutil -c user/$NOTSPAM/INBOX
}
}

[ -d $TDIR ] && rm -rf $TDIR


Run the script in a way you like.
I put it directly to a crontab. Root's crontab.

Enjoy.