Thursday, November 20, 2014

Sudo on Minix 3.1.8

Minix 3.3.0 came out a while ago and I had all kinds of fun playing with it.  I'd long been running 3.2.1 but never gave 3.1.8 a try at all.  The fun I had with 3.3.0 got me motivated though and a few weeks back I gave it a shot.

It was fairly straightforward, for the most part.  A few things here and there reminded me of 2.0 but the overall user experience was similar to 3.2.1.  Getting various bits of software running required many of the same tweaks that 3.3.0 and 3.2.1 required, but the most difficult bit by far was sudo.

Sudo 1.7.something-or-other is available via pkgin but it dumps core whenever you do anything with it.

Sudo version 1.6.9p23 has been reliably portable for me though, so I gave it a try.  It took a while to work around various issues, but eventually I got it working.  If anyone out there is interested, here are the tricks:

The code requires a little hackery.

Add the following line after the includes in interfaces.c

#define IFF_LOOPBACK IFF_UP

Edit sudo.tab.c and comment out:

# include <search.h>

it should look like this when you're done:

/*# include <search.h>*/

Minix 3.1.8's implementation of getgroups always returns -1.  This causes a few problems for sudo.  To solve them, edit set_perms.c and make 3 modifications.

Make the declaration of runas_groups (around line 376) look like:

static GETGROUPS_T *runas_groups = NULL;
Update a section of the function runas_setgroups() as follows:

...
if (runas_ngroups <= 0) {
pw = runas_pw ? runas_pw : sudo_user.pw;
if (initgroups(pw->pw_name, pw->pw_gid) < 0)
log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");

if ((runas_ngroups = getgroups(0, NULL)) > 0) {
runas_groups = emalloc2(runas_ngroups, sizeof(GETGROUPS_T));
if (getgroups(runas_ngroups, runas_groups) < 0)
log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector");
}

} else {
...

Update the function restore_groups() as follows:

static void
restore_groups()
{
if (user_ngroups > 0) {
if (setgroups(user_ngroups, user_groups) < 0)
log_error(USE_ERRNO|MSG_ONLY, "can't reset user group vector");
}
}

That third modification is actually a workaround for a bug (or feature) in setgroups().  It goes completely haywire if user_ngroups is -1.  I'll bet that this is the problem that the version of sudo available via pkgin has too.  There might be a libc update that fixes this issue but for now we'll just work around it.

Now build and install.  Some options needs to be enabled in the header files with the _POSIX_SOURCE macro, so we'll pass that in.  I also like to install it under it's own directory tree, so I use the --prefix option for that.

CPPFLAGS="-D_POSIX_SOURCE" ./configure --prefix=/usr/local/sudo-1.6.9p23
make
su
make install

The default permissions are wrong for Minix though, so they need to be set manually:

chmod 555 /usr/local/sudo-1.6.9p23/bin/sudo
chmod u+s /usr/local/sudo-1.6.9p23/bin/sudo

Now add a line for your user (dmuse in my case) to /etc/sudoers.

dmuse ALL=(ALL) NOPASSWD: ALL

Yes, the sudoers file is installed under /etc independent of the --prefix option used earlier.  The NOPASSWD option makes it so you don't have to enter a password.

And the last step is to add /usr/local/sudo-1.6.9p23/bin to your PATH in ~/.ashrc

export PATH=$HOME/bin:/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin:\
/usr/pkg/X11R6/bin:/usr/pkg/bin:/usr/pkg/sbin:/usr/llvm/bin:\
/usr/local/sudo-1.6.9p23/bin

And that's it.  Re-login and sudo should work as expected.

$ sudo ls -l /
total 44
drwxr-xr-x 2 root operator 2880 Sep 4 2010 bin
drwxr-xr-x 3 root operator 384 Sep 4 2010 boot
drwxr-xr-x 2 root operator 29120 Sep 20 02:47 dev
drwxr-xr-x 3 root operator 2304 Nov 20 22:53 etc
drwxrwxrwx 5 bin bin 320 Sep 20 02:55 home
drwxrwxrwx 2 root operator 128 Sep 20 02:45 mnt
drwx------ 2 root operator 768 Sep 20 04:09 root
drwxr-xr-x 2 root operator 896 Sep 4 2010 sbin
drwxrwxrwt 2 root operator 640 Nov 20 23:52 tmp
drwxrwxrwx 23 bin bin 1536 Sep 20 03:27 usr
drwxr-xr-x 3 root operator 256 Sep 20 02:45 var

Woohoo!  Sudo on Minix 3.1.8.

Wednesday, November 12, 2014

Windows Progress...

SQL Relay has classically run on Unix and Linux but not Windows. A few years ago I got the C/C++ API working on Windows and added a C# API and .NET data provider. I got a few of the command-line programs working too, but that was about all you could do on Windows for quite a while. A few months ago when I got the Perl, Python and PHP API's working on Windows along with the rest of the command line clients, but still, only the client side software worked.

Since then I've made quite a bit of progress getting the server working too. And tonight things really started to come together...



That's the SQL Relay server running on Windows, connected to a database running on Linux, accessed by sqlrsh, also running on Windows.

And it can be accessed remotely too.



That's the same SQL Relay server running on Windows, accessed by sqlrsh running in a separate Linux VM.

There are a number of things that don't work yet like sqlr-stop and various plugins, and there are several things that just haven't been tested yet, but the big things are coming along nicely. I expect to be able to announce preliminary support for the SQL Relay server software on Windows in the next release.

Tuesday, October 28, 2014

oracle-jvm error...

I'm not sure how long ago this happened, but there are now lots of different JVM's available for Debian and Ubuntu systems: openjdk-6, openjdk-7, openjdk-8, oracle-jvm-7 and oracle-jvm-8. Possibly more...


SQL Relay 0.57 has no trouble detecting the openjdk's, but doesn't properly detect oracle-jvm's and the build fails. I ran into this error trying to build on a Raspberry PI running Raspbian, but a few people have reported the same error on Debian and Ubuntu sytems.


There are 3 workarounds:


Disable Java

If you're not using SQL Relay with java then you can add --disable-java to the configure command and SQL Relay won't even try to build against oracle-jvm.


Replace Oracle JVM with OpenJDK

This may be tricky. I'm not sure which packages have a hard dependency on oracle-jvm as opposed to just needing some version of Java. Your mileage may vary.


Patch the Configure Script

Edit the configure script in the SQL Relay source distribution and look for a line like:


   for i in `ls -d /usr/java/jdk* /usr/java/j2sdk* /usr/local/jdk* 2> /dev/null` /usr/java 
/usr/local/java `ls -d /usr/local/openjdk* /usr/pkg/java/openjdk* 2> /dev/null` `ls -d /usr/lib64/jvm/java 2> /dev/null` 
`ls -d /usr/lib64/jvm/java-1.8* 2> /dev/null` `ls -d /usr/lib64/jvm/java-1.7* 2> /dev/null` `ls -d /usr/lib64
/jvm/java-1.6* 2> /dev/null` `ls -d /usr/lib/jvm/java 2> /dev/null` `ls -d /usr/lib/jvm/java-1.8* 2> /dev/null` `ls -d 
/usr/lib/jvm/java-1.7* 2> /dev/null` `ls -d /usr/lib/jvm/java-1.6* 2> /dev/null` /System/Library/Frameworks
/JavaVM.framework/Versions/Current /usr /usr/local

and replace it with these lines:


   for i in `ls -d /usr/java/jdk* /usr/java/j2sdk* /usr/local/jdk* 2> /dev/null` \
    /usr/java \
    /usr/local/java \
    `ls -d /usr/local/openjdk* /usr/pkg/java/openjdk* 2> /dev/null` \
    `ls -d /usr/lib64/jvm/java 2> /dev/null` \
    `ls -d /usr/lib64/jvm/java-1.8* 2> /dev/null` \
    `ls -d /usr/lib64/jvm/java-1.7* 2> /dev/null` \
    `ls -d /usr/lib64/jvm/java-1.6* 2> /dev/null` \
    `ls -d /usr/lib64/jvm/jdk-7-* 2> /dev/null` \
    `ls -d /usr/lib64/jvm/jdk-8-* 2> /dev/null` \
    `ls -d /usr/lib/jvm/java 2> /dev/null` \
    `ls -d /usr/lib/jvm/java-1.8* 2> /dev/null` \
    `ls -d /usr/lib/jvm/java-1.7* 2> /dev/null` \
    `ls -d /usr/lib/jvm/java-1.6* 2> /dev/null` \
    `ls -d /usr/lib/jvm/jdk-7-* 2> /dev/null` \
    `ls -d /usr/lib/jvm/jdk-8-* 2> /dev/null` \
    /System/Library/Frameworks/JavaVM.framework/Versions/Current \
    /usr \
    /usr/local

One of those three solutions should work.


The source has been updated and it's fixed in CVS. The next release will include the fix too.

Saturday, October 11, 2014

Oops...

It appears that I forgot to run "make distclean" before building that last round of tar.gz and zip files for both Rudiments and SQL Relay. So, if you downloaded last week (the week of October 6th, 2014), or the week before, then you may have had trouble building. Configure probably ran, but make might not have made anything.


Who knows what platform the binaries that were in there ran on? Fedora 20 x64 maybe... Maybe not though.


Anyway...


I just updated the tar.gz and zip files with clean versions. I also downloaded and verified them this time. They ought to be correct.


Thanks Florin... If you hadn't pointed it out, I might never have noticed.

Saturday, October 4, 2014

SQL Relay - 0.57 is out

SQL Relay 0.57 is now available!


Windows Support

Support for Windows is much improved in this release. The command line clients all work now - sqlrsh, sqlr-export, sqlr-import, etc. The C/C++, C# and ADO.NET API's have worked for a while, but are now joined by native API's for Perl, Python, PHP and Java as well as drivers for Perl DBI, Python DB and PHP PDO.


It is possible to build all of this on Windows using MS Visual Studio or MS Visual Studio Express but it is currently quite difficult and requires specific versions of things to be installed in the right places. PHP is especially difficult to work with. In fact, I'm honestly not sure how 3rd party developers are expected to develop drivers for Windows. I had to shoehorn the headers in manually from the source code.


However... The SQL Relay Binary Distribution for Windows is now available (for a few bucks) and provides installers for binary versions of the above-mentioned software.


So... in addition to just accessing SQL Relay from command line clients, SQL Relay applications, including web-based applications, can now be developed for Windows in C, C++, C# (and other .NET languages), Perl, Python, PHP and Java.


Give it a try, let me know if you run into trouble.


Oracle "describe table" Improvements

In sqlrsh if you run "describe tablename" it returns info about the columns of the table - name, type, size, etc. This is accomplished by a call to the getColumnList() method of the C++ API. All SQL Relay API's support this method, and it has been improved.


For oracle tables, if a column is a primary, unique or foreign key, that information is now given. In previous releases it was not. This is a fairly expensive operation, as it turns out, so there is a config parameter to disable looking up keys. See disablekeylookup=yes/no in the oracle connection string in the SQL Relay Configuration Reference for more info.


Also, if you run "describe" on a synonym to a table in another schema, it will now return information about that table. In previous releases, only tables could be described.


Rudiments Improvements

The Rudiments library that SQL Relay depends on has been updated to randomize the list of hosts returned by DNS server when using round-robin DNS. If you are using round robin DNS to distribute SQL Relay clients over a pool of SQL Relay servers, then the behavior may different than in previous releases. In particular, if one host is down, then rather than slamming the next host in the list with all of the downed host's traffic, load will be distributed over the remaining hosts. This feature was added to work around an issue with many recent-ish implementations of getaddrinfo().


Rudiments has also been updated to support kqueue, epoll, port_create, /dev/poll, poll and select in its listener class. There should be no concerns now about large numbers of clients queuing up on the listener, or with listener performance with regard to using select internally.


See the rudiments release announcement for more information on these updates.


Bug Fixes and Minor Improvements

This release features a few bug fixes and minor improvements too.


The Python API's getRowDictionary method had a bug where None's were being returned as 0's when getNullsAsNones was set. That's fixed now.


Sensible errors are now returned when the format of a numeric bind variable is incorrect when using mysql, firebird or oracle. An error was fixed that could cause mysql connection to loop up if alphanumeric bind variable names were used instead of numbers. A bind-variable translation bug was fixed that could cause variables not to be translated when multiple formats are used in the same query and one of them is the correct format too.


The --with-system-libtool configure option was broken but it's fixed now.


Minix 3.3.0 is now supported. At least the client side is. Ie. you can access Oracle from Minix 3.3.0 using sqlrsh and SQL Relay running on another system. The server-side stuff doens't work yet. The Minix kernel doesn't support semaphores by default and Minix 3.3.0 ships without kernel source. I'm not sure if it supports semaphores at all though, so maybe that's moot.


The drop-in replacement library for MySQL had bugs with its implementations of mysql_row_seek() and mysql_row_tell(). Those are fixed now.


The configure script properly detects Maria DB on Ubuntu 14.04.1 now.



Give it a try and report any bugs that you find!

Friday, October 3, 2014

Rudiments - 0.48 is out

Rudiments 0.48 is now available!


This release has a few fairly important features.


Random Number Generation

The randomnumber class has been updated to support CryptGenRandom (on Windows), arc4random, random_r, rand_r, lrand48_r, random, rand and lrand48. It will use whichever of those it can find, in that order. The class has static and non-static members now. When the non-static members are used, the class can be seeded once and numbers (or scaled numbers) can be generated over and over without explicitly re-seeding.


Inet Socket Clients

Several improvements have been made to the inetsocketclient class.


Internally, inetsocketclient uses either getaddrinfo() or some variant of gethostbyname(), depending on what's available.


First, a bug was fixed that caused timeouts not to work on systems that don't have getaddrinfo().


Second, it seems that the behavior of getaddrinfo() has changed over the years and a workaround has been introduced to deal with some issues that the new behavior causes...


When round-robin DNS is used, gethostbyname() and getaddrinfo() fetch the entire list of IP addresses that the host name resolves to. The inetsocketclient's connect() method gets this list and tries to connect to each of these IP's, in the order that they were returned by gethostbyname()/getaddrinfo(). When round-robin DNS is used, the order of the IP's in the list is rotated with each DNS request. This can be used to implement a simple load-balancing scheme.


"Recent" (I'm not sure how recent) implementations of getaddrinfo() have begun sorting the IP's, defeating round-robin DNS entirely. Some implementations have a /etc/gai.conf file that allow a sortv4=no directive, but many do not. Some implementations randomize the list of IP's. Some implementations return them in the order that the DNS server returned them in.


Rudiments has no way of knowing what the behavior of getaddrinfo() is, so now, by default, the list of IP addresses is randomized. For the sake of consistency, it's randomized whether it uses getaddrinfo() internally or some variant of gethostbyname(). Methods have been added to the class to enable or disable this behavior too.


Randomization provides a benefit over round-robin DNS as well. With round-robin DNS, when a host goes down, the next host in the list will receive all of the downed host's traffic. With randomization, traffic is distributed evenly over the hosts that are still up.


listner class

The listener class has been refactored entirely to match the paradigms established by kqueue, epoll, /dev/poll, etc. It now supports kqueue, epoll, port_create, /dev/poll, poll and select internally as well, and will use whichever is available, in that order.


In the previous release, support was added for kqueue, epoll and poll but the implementation still did some inefficient things like rebuilding the list of file descriptors to listen on before each iteration. The list is only rebuilt if a file descriptor is added or removed now.


Minix 3.3.0

Minix 3.3.0 came out since the last release and it's now supported.


General Bug Fixes and Improvements

Some general bug fixes and improvements were implemented as well. Cygwin builds ought to work correctly now. Setting file permissions ought to work natively on Windows now too.

Monday, July 14, 2014

SQL Relay - 0.56 is out

SQL Relay version 0.56 is now available!


You might want to get this one. A subtle memory leak is fixed in this release. If you really can't upgrade and need a fix for a previous release, contact me and we can work something out.


Amazing new features:

Perl, PHP, Python and Java API's all build and work on Windows. You still have to build them from source though, and it's a pain. If you need Windows binaries, contact me and we can work something out.


Intelligent defaults have been added for a lot of the configuration parameters. The sqlrelay.conf file can be much more stripped down now. I also added a Configuration Guide that walks you through various configurations from minimal to complex. Enjoy.


The PHP PDO API now has a custom statement attribute PDO::SQLRELAY_ATTR_GET_NULLS_AS_EMPTY_STRINGS that can be set to true or false to cause it to return NULL values as NULLs or empty strings.


New parameters have been added for connecting to MySQL via SSL. See the Configuration Reference for more detail.


Amazing bug fixes:

The PHP PDO driver handles float values correctly now. Previously it was converting them to strings. It also handles NULL integers correctly now rather than converting them to 0's.


There was a bug in the sqlr-scaler that could cause it to use a noticeable amount of the CPU when sitting idle. That's fixed now.


Some installations of Oracle instant client might not have been properly detected before, but they are now.


There was a bug that caused problems with DB2 7.X. It's fixed now.


sessionhandler="thread" and listenertimeout!="0" ought to work now. This is still sketchy and experimental though.


Internal stuff:

A lot of code has been reorganized internally. Many things have been modularized and simplified. Frameworks have been built and some things have been re-implemented using them. This is ongoing. More of this will be done over the next few releases.


Full ChangeLog follows:


  • removed VERSION from perl api bootstrap
  • reorganized and simplified perl api code
  • got perl api working on windows with ActivePerl
  • perl api uninstall cleans up better now
  • got python api working on windows with ActivePython
  • consolidated php include tweaks
  • got java api working on windows
  • updated pdo driver to convert float fields to strings rather than ints
  • updated pthread test to match rudiments pthread test
  • moved everything done by children of sqlwriter interface into individual translations
  • added plugin-based authentication framework
  • reorganized code tree a bit
  • reworked default values to enable more minimal configurations
  • updated configuration docs and added configuration guide
  • fixed cast issue with firebird 1.5
  • added result set translation framework and re-implemented date translation using it
  • fixed millisecond->nanosecond confusion in sqlr-scaler
  • fixed subtle oracle instantclient version detection bug
  • added null input bind support to sqlrsh
  • fixed php pdo driver to return null rather than 0 for null integer fields and bind null rather than 0 for null integer input binds
  • added attribute to return nulls as nulls or empty strings to php pdo
  • added parameters for connecting to mysql via ssl
  • added a few tweaks to support DB2 < 8.0
  • fixed bad return value type in python getConnectionPort method
  • fixed sessionhandler="thread" with listenertimeout!="0"