Thursday, November 13, 2008

HTC Diamond as a Rndis Modem (GPRS/EDGE/HSDPA)

Using HTC Diamond as a Rndis modem

Hi, after a small amount of investigation I have finally got the HTC Diamond working as a Rndis modem over the USB port.

What this means is that you can use the Internet connection sharing function of the Diamond to get a computer onto the Internet using the H or G phone data connection.

Please note that the first steps of this guide will work for any ACTIVESYNC connected HTC phone that has the Connection Sharing (it's in the Connection Manager on other HTC phones)

Obviously using data on your mobile costs money so be aware of this and make sure you have a package that has reasonable charges.

finally I have only tested this on an ORANGE HTC Diamond in the UK.

The reason you have to modify the source is that if you don't the rndis fails with an error like (this is seen in the /var/log/syslog)

Code:

[355.215268] rndis_host 5-3:1.0: dev can't take 1558 byte packets (max 1536)


you need a working internet connection to set this up

1. Install Pre-requisites
2. Get the Source
3. Modify the source (Diamond only)
4. Compile and make and install
5. Start the Internet Connection Sharing
6. Plug in the Phone (USB)


Once you have done steps 1-4 you will only ever need to do steps 5 & 6 to get re-connected.



Step 1 - Install Pre-requisites

open a terminal (use same terminal in next steps)

Code:

$ sudo apt-get install subversion

Step 2 - Get the Source

Code:

$ svn co http://synce.svn.sourceforge.net/svnroot/synce/trunk/usb-rndis-lite
cd usb-rndis-lite/

Step 3 - Modify the source (Diamond only)

Code:

$ gedit rndis_host.c

on line 524, find this bit

Code:

if (tmp <>hard_mtu) {
dev_err(&intf->dev,
"dev can't take %u byte packets (max %u)\n",
dev->hard_mtu, tmp);
goto fail;
}

change it to this

Code:

if (tmp <>hard_mtu) {
dev_err(&intf->dev,
"dev can't take %u byte packets (max %u)\n",
dev->hard_mtu, tmp);
retval = -EINVAL;
/* goto fail;*/
}

save the file

Step 4 - Compile and make and install

Code:

$ make
$ sudo ./clean.sh
$ sudo make install

Step 5 - Start the Internet Connection Sharing

On OLD Tytn II's open Comm Manager on your phone and click on the Internet Sharing Now make sure USB is selected and choose connect

On Diamonds it's a seperate program called Internet Connection Sharing

Step 6 - Plug in the Phone (USB)

Plug the phone in, once the Phone has a data connection the Internet connection sharing will say connecting, then connected.

If this takes a while the dhcp may timeout and you will have to run the following command.

Code:

$ sudo dhclient

You should then see that you have an ip on the rndis device

Code:

$ ifconfig

Taken From: http://ubuntuforums.org/archive/index.php/t-935203.html

Monday, October 27, 2008

Change Your Mac Address in Linux

# In order to change your MAC address just type the following:

$ sudo ifconfig eth0 down hw ether 0A:0B:0C:0D:AA:BB


Note: "0A:0B:0C:0D:AA:BB" is just an example, you should put there the disired MAC address

Note: bringing down the interface (sudo ifconfig eth0 down) and them changing the mac address (sudo ifconfig eth0 hw ether 0A:0B:0C:0D:AA:BB) did not work, instead i did all in one line as shown above



# Now bring the interface back up, and you are ready to go.

$ sudo ifconfig eth0 up

Wednesday, October 15, 2008

Secured Remote Desktop/Application Sessions

Run graphical applications from afar, securely.

There are many different ways to control a Linux system over a network, and many reasons you might want to do so. When covering remote control in past columns, I've tended to focus on server-oriented usage scenarios and tools, which is to say, on administering servers via text-based applications, such as OpenSSH. But, what about GUI-based applications and remote desktops?

Remote desktop sessions can be very useful for technical support, surveillance and remote control of desktop applications. But, it isn't always necessary to access an entire desktop; you may need to run only one or two specific graphical applications.

In this month's column, I describe how to use VNC (Virtual Network Computing) for remote desktop sessions and OpenSSH with X forwarding for remote access to specific applications. Our focus here, of course, is on using these tools securely, and I include a healthy dose of opinion as to the relative merits of each.

Remote Desktops vs. Remote Applications

So, which approach should you use, remote desktops or remote applications? If you've come to Linux from the Microsoft world, you may be tempted to assume that because Terminal Services in Windows is so useful, you have to have some sort of remote desktop access in Linux too. But, that may not be the case.

Linux and most other UNIX-based operating systems use the X Window System as the basis for their various graphical environments. And, the X Window System was designed to be run over networks. In fact, it treats your local system as a self-contained network over which different parts of the X Window System communicate.

Accordingly, it's not only possible but easy to run individual X Window System applications over TCP/IP networks—that is, to display the output (window) of a remotely executed graphical application on your local system. Because the X Window System's use of networks isn't terribly secure (the X Window System has no native support whatsoever for any kind of encryption), nowadays we usually tunnel X Window System application windows over the Secure Shell (SSH), especially OpenSSH.

The advantage of tunneling individual application windows is that it's faster and generally more secure than running the entire desktop remotely. The disadvantages are that OpenSSH has a history of security vulnerabilities, and for many Linux newcomers, forwarding graphical applications via commands entered in a shell session is counterintuitive. And besides, as I mentioned earlier, remote desktop control (or even just viewing) can be very useful for technical support and for security surveillance.

Using OpenSSH with X Window System Forwarding

Having said all that, tunneling X Window System applications over OpenSSH may be a lot easier than you imagine. All you need is a client system running an X server (for example, a Linux desktop system or a Windows system running the Cygwin X server) and a destination system running the OpenSSH dæmon (sshd).

Note that I didn't say “a destination system running sshd and an X server”. This is because X servers, oddly enough, don't actually run or control X Window System applications; they merely display their output. Therefore, if you're running an X Window System application on a remote system, you need to run an X server on your local system, not on the remote system. The application will execute on the remote system and send its output to your local X server's display.

Suppose you've got two systems, mylaptop and remotebox, and you want to monitor system resources on remotebox with the GNOME System Monitor. Suppose further you're running the X Window System on mylaptop and sshd on remotebox.

First, from a terminal window or xterm on mylaptop, you'd open an SSH session like this:

mick@mylaptop:~$ ssh -X admin-slave@remotebox
admin-slave@remotebox's password: **********
Last login: Wed Jun 11 21:50:19 2008 from dtcla00b674986d
admin-slave@remotebox:~$

Note the -X flag in my ssh command. This enables X Window System forwarding for the SSH session. In order for that to work, sshd on the remote system must be configured with X11Forwarding set to yes in its /etc/ssh/sshd.conf file. On many distributions, yes is the default setting, but check yours to be sure.

Next, to run the GNOME System Monitor on remotebox, such that its output (window) is displayed on mylaptop, simply execute it from within the same SSH session:

admin-slave@remotebox:~$ gnome-system-monitor &

The trailing ampersand (&) causes this command to run in the background, so you can initiate other commands from the same shell session. Without this, the cursor won't reappear in your shell window until you kill the command you just started.

At this point, the GNOME System Monitor window should appear on mylaptop's screen, displaying system performance information for remotebox. And, that really is all there is to it.

This technique works for practically any X Window System application installed on the remote system. The only catch is that you need to know the name of anything you want to run in this way—that is, the actual name of the executable file.

If you're accustomed to starting your X Window System applications from a menu on your desktop, you may not know the names of their corresponding executables. One quick way to find out is to open your desktop manager's menu editor, and then view the properties screen for the application in question.

For example, on a GNOME desktop, you would right-click on the Applications menu button, select Edit Menus, scroll down to System/Administration, right-click on System Monitor and select Properties. This pops up a window whose Command field shows the name gnome-system-monitor.

Figure 1 shows the Launcher Properties, not for the GNOME System Monitor, but instead for the GNOME File Browser, which is a better example, because its launcher entry includes some command-line options. Obviously, all such options also can be used when starting X applications over SSH.

Figure 1. Launcher Properties for the GNOME File Browser (Nautilus)

If this sounds like too much trouble, or if you're worried about accidentally messing up your desktop menus, you simply can run the application in question, issue the command ps auxw in a terminal window, and find the entry that corresponds to your application. The last field in each row of the output from ps is the executable's name plus the command-line options with which it was invoked.

Once you've finished running your remote X Window System application, you can close it the usual way (selecting Exit from its File menu, clicking the x button in the upper right-hand corner of its window and so forth). Don't forget to close your SSH session too, by issuing the command exit in the terminal window where you're running SSH.

Virtual Network Computing (VNC)

Now that I've shown you the preferred way to run remote X Window System applications, let's discuss how to control an entire remote desktop. In the Linux/UNIX world, the most popular tool for this is Virtual Network Computing, or VNC.

Originally a project of the Olivetti Research Laboratory (which was subsequently acquired by Oracle and then AT&T before being shut down), VNC uses a protocol called Remote Frame Buffer (RFB). The original creators of VNC now maintain the application suite RealVNC, which is available in free and commercial versions, but TightVNC, UltraVNC and GNOME's vino VNC server and vinagre VNC client also are popular.

VNC's strengths are its simplicity, ubiquity and portability—it runs on many different operating systems. Because it runs over a single TCP port (usually TCP 5900), it's also firewall-friendly and easy to tunnel.

Its security, however, is somewhat problematic. VNC authentication uses a DES-based transaction that, if eavesdropped-on, is vulnerable to optimized brute-force (password-guessing) attacks. This vulnerability is exacerbated by the fact that many versions of VNC support only eight-character passwords.

Furthermore, VNC session data usually is transmitted unencrypted. Only a couple flavors of VNC support TLS encryption of RFB streams, and it isn't clear how securely TLS has been implemented even in those. Thus, an attacker using a trivially hacked VNC client may be able to reconstruct and view eavesdropped VNC streams.

Luckily, as it operates over a single TCP port, VNC is easy to tunnel through SSH, through Virtual Private Network (VPN) sessions and through TLS/SSL wrappers, such as stunnel. Let's look at a simple VNC-over-SSH example.

Tunneling VNC over SSH

To tunnel VNC over SSH, your remote system must be running an SSH dæmon (sshd) and a VNC server application. Your local system must have an SSH client (ssh) and a VNC client application.

Our example remote system, remotebox, already is running sshd. Suppose it also has vino, which is also known as the GNOME Remote Desktop Preferences applet (on Ubuntu systems, it's located in the System menu's Preferences section). First, presumably from remotebox's local console, you need to open that applet and enable remote desktop sharing. Figure 2 shows vino's General settings.

Figure 2. General Settings in GNOME Remote Desktop Preferences (vino)

If you want to view only this system's remote desktop without controlling it, uncheck Allow other users to control your desktop. If you don't want to have to confirm remote connections explicitly (for example, because you want to connect to this system when it's unattended), you can uncheck the Ask you for confirmation box. Any time you leave yourself logged in to an unattended system, be sure to use a password-protected screensaver!

vino is limited in this way. Because vino is loaded only after you log in, you can use it only to connect to a fully logged-in GNOME session in progress—not, for example, to a gdm (GNOME login) prompt. Unlike vino, other versions of VNC can be invoked as needed from xinetd or inetd. That technique is out of the scope of this article, but see Resources for a link to a how-to for doing so in Ubuntu, or simply Google the string “vnc xinetd”.

Continuing with our vino example, don't close that Remote Desktop Preferences applet yet. Be sure to check the Require the user to enter this password box and to select a difficult-to-guess password. Remember, vino runs in an already-logged-in desktop session, so unless you set a password here, you'll run the risk of allowing completely unauthenticated sessions (depending on whether a password-protected screensaver is running).

If your remote system will be run logged in but unattended, you probably will want to uncheck Ask you for confirmation. Again, don't forget that locked screensaver.

We're not done setting up vino on remotebox yet. Figure 3 shows the Advanced Settings tab.

Figure 3. Advanced Settings in GNOME Remote Desktop Preferences (vino)

Several advanced settings are particularly noteworthy. First, you should check Only allow local connections, after which remote connections still will be possible, but only via a port-forwarder like SSH or stunnel. Second, you may want to set a custom TCP port for vino to listen on via the Use an alternative port option. In this example, I've chosen 20226. This is an instance of useful security-through-obscurity; if our other (more meaningful) security controls fail, at least we won't be running VNC on the obvious default port.

Also, you should check the box next to Lock screen on disconnect, but you probably should not check Require encryption, as SSH will provide our session encryption, and adding redundant (and not-necessarily-known-good) encryption will only increase vino's already-significant latency. If you think there's only a moderate level of risk of eavesdropping in the environment in which you want to use vino—for example, on a small, private, local-area network inaccessible from the Internet—vino's TLS implementation may be good enough for you. In that case, you may opt to check the Require encryption box and skip the SSH tunneling.

(If any of you know more about TLS in vino than I was able to divine from the Internet, please write in. During my research for this article, I found no documentation or on-line discussions of vino's TLS design details whatsoever—beyond people commenting that the soundness of TLS in vino is unknown.)

This month, I seem to be offering you more “opt-out” opportunities in my examples than usual. Perhaps I'm becoming less dogmatic with age. Regardless, let's assume you've followed my advice to forego vino's encryption in favor of SSH.

At this point, you're done with the server-side settings. You won't have to change those again. If you restart your GNOME session on remotebox, vino will restart as well, with the options you just set. The following steps, however, are necessary each time you want to initiate a VNC/SSH session.

On mylaptop (the system from which you want to connect to remotebox), open a terminal window, and type this command:

mick@mylaptop:~$ ssh -L 20226:remotebox:20226 admin-slave@remotebox

OpenSSH's -L option sets up a local port-forwarder. In this example, connections to mylaptop's TCP port 20226 will be forwarded to the same port on remotebox. The syntax for this option is “-L [localport]:[remote IP or hostname]:[remoteport]”. You can use any available local TCP port you like (higher than 1024, unless you're running SSH as root), but the remote port must correspond to the alternative port you set vino to listen on (20226 in our example), or if you didn't set an alternative port, it should be VNC's default of 5900.

That's it for the SSH session. You'll be prompted for a password and then given a bash prompt on remotebox. But, you won't need it except to enter exit when your VNC session is finished. It's time to fire up your VNC client.

vino's companion client, vinagre (also known as the GNOME Remote Desktop Viewer) is good enough for our purposes here. On Ubuntu systems, it's located in the Applications menu in the Internet section. In Figure 4, I've opened the Remote Desktop Viewer and clicked the Connect button. As you can see, rather than remotebox, I've entered localhost as the hostname. I've also entered port number 20226.

Figure 4. Using vinagre to Connect to an SSH-Forwarded Local Port

When I click the Connect button, vinagre connects to mylaptop's local TCP port 20226, which actually is being listened on by my local SSH process. SSH forwards this connection attempt through its encrypted connection to TCP 20226 on remotebox, which is being listened on by remotebox's vino process.

At this point, I'm prompted for remotebox's vino password (shown in Figure 2). On successful authentication, I'll have full access to my active desktop session on remotebox.

To end the session, I close the Remote Desktop Viewer's session, and then enter exit in my SSH session to remotebox—that's all there is to it.

This technique is easy to adapt to other versions of VNC servers and clients, and probably also to other versions of SSH—there are commercial alternatives to OpenSSH, including Windows versions. I mentioned that VNC client applications are available for a wide variety of platforms; on any such platform, you can use this technique, so long as you also have an SSH client that supports port forwarding.

Conclusion

Thus ends my crash course on how to control graphical applications over networks. I hope my examples of both techniques, SSH with X forwarding and VNC over SSH, help you get started with whatever particular distribution and software packages you prefer. Be safe!

Mick Bauer (darth.elmo@wiremonkeys.org) is Network Security Architect for one of the US's largest banks. He is the author of the O'Reilly book Linux Server Security, 2nd edition (formerly called Building Secure Servers With Linux), an occasional presenter at information security conferences and composer of the “Network Engineering Polka”.

Taken From: Linux Journal Contents #173, September 2008

Friday, October 10, 2008

Adding a User to a Group - Linux

Q. How can I add a user to a group under Linux operating system?

A. You can use useradd or usermod commands to add a user to a group. useradd command creates a new user or update default new user information. usermod command modifies a user account i.e. it is useful to add user to existing group. There are two types of group. First is primary user group and other is secondary group. All user account related information is stored in /etc/passwd, /etc/shadow and /etc/group files to store user information.

useradd example - Add a new user to secondary group

Use useradd command to add new users to existing group (or create a new group and then add user). If group does not exist, create it. Syntax:
useradd -G {group-name} username
Create a new user called vivek and add it to group called developers. First login as a root user (make sure group developers exists), enter:
# grep developers /etc/group
Output:

developers:x:1124:

If you do not see any output then you need to add group developers using groupadd command:
# groupadd developers
Next, add a user called vivek to group developers:
# useradd -G developers vivek
Setup password for user vivek:
# passwd vivek
Ensure that user added properly to group developers:
# id vivekOutput:

uid=1122(vivek) gid=1125(vivek) groups=1125(vivek),1124(developers)

Please note that capital G (-G) option add user to a list of supplementary groups. Each group is separated from the next by a comma, with no intervening whitespace. For example, add user jerry to groups admins, ftp, www, and developers, enter:
# useradd -G admins,ftp,www,developers jerry

useradd example - Add a new user to primary group

To add a user tony to group developers use following command:
# useradd -g developers tony
# id tony

uid=1123(tony) gid=1124(developers) groups=1124(developers)
Please note that small -g option add user to initial login group (primary group). The group name must exist. A group number must refer to an already existing group.

usermod example - Add a existing user to existing group

Add existing user tony to ftp supplementary/secondary group with usermod command using -a option ~ i.e. add the user to the supplemental group(s). Use only with -G option :


# usermod -a -G ftp tonyChange existing user tony primary group to www:
# usermod -g www tony

Taken From: http://www.cyberciti.biz/faq/howto-linux-add-user-to-group/

Wednesday, October 1, 2008

Storing Object Oriented Data on a Database

Relational databases are really great for storing and retrieving data, but sometimes, they aren't quite up to the task. Joe Celko, whose SQL for Smarties books are among my favorites, dedicated an entire volume to the issue of trees and hierarchies. These data structures might be common and useful in most programming languages, but they can be difficult to model as tables, particularly if you care about efficient use of the database. Things become even trickier if you're dealing with a number of related, but distinct, types of entities, such as different types of employees or different types of vehicles.

One way to solve this problem is not to use relational databases. Objects can be quite good at handling trees and arrays, as well as inheritance hierarchies. Furthermore, object databases do exist, and the Python-based Zope application framework has demonstrated that it's even possible to have object databases in production. Gemstone's demonstration of Ruby running on top of its Smalltalk VM, with its accompanying object database, means that Ruby programmers soon might have access to similar technology.

But, object databases still are far from the mainstream. Most Web developers have access to a relational database, and not much else. Is there anything that we can do for these people?

This month, we take a look at two different ways we can handle data that doesn't quite fit into a relational database. These techniques are quite different from one another, and they don't even come close to the full range of possibilities you can get with a relational database. But, they both work and are used in production environments—and if your data doesn't seem to fit into standard database paradigms, you might want to consider one of them.

PostgreSQL's Table Inheritance
Some data-modeling issues are typically even harder to deal with. For example, a classic introduction to the world of object-oriented programming describes a human resources department. The HR department tracks employees, all of whom have some common characteristics. But, some employees are programmers, some are secretaries, and some are managers—and each of the employee types has specific data that needs to be associated with them.

In an object-oriented world, it's easy to model this. You create an employee class, and then create multiple subclasses of programmer, secretary and manager. Subclassing creates an “is-a” relationship, such that a programmer is an employee. This means that programmers have all the attributes of an employee, but also have some additional characteristics that distinguish them from an ordinary employee. With these subclasses in place, we then can create an array (or any other data structure) of people in our company, knowing that although some are programmers and others are secretaries, they're all employees and can be treated as such.

Translating this idea to the world of relational databases can be a bit tricky. One solution is to use inheritance in your database tables. PostgreSQL has done this for years; thus, it's called an object-relational database by many users. You can do the following in PostgreSQL, for example:


CREATE TABLE Employees (
id SERIAL,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email_address TEXT NOT NULL,

PRIMARY KEY(id),
UNIQUE(email_address)
);

CREATE TABLE Programmers (
main_language TEXT NOT NULL
) INHERITS(Employees);

CREATE TABLE Secretaries (
words_per_minute INTEGER NOT NULL
) INHERITS(Employees);


INSERT INTO Employees (first_name, last_name, email_address)
VALUES ('George', 'Washington', 'georgie@whitehouse.gov');

INSERT INTO Programmers (first_name, last_name,
email_address, main_language)
VALUES ('Linus', 'Torvalds', 'torvalds@osdl.org', 'C');

INSERT INTO Secretaries (first_name, last_name,
email_address, words_per_minute)
VALUES ('Condoleezza', 'Rice', 'rice@state.gov', 10);


If we ask for all employees in the system, we'll get all three of the people we have entered:


atf=# select * from employees;
id first_name last_name email_address
----+------------+------------+------------------------
1 George Washington georgie@whitehouse.gov
2 Linus Torvalds torvalds@osdl.org
3 Condoleezza Rice rice@state.gov
(3 rows)


Of course, this query shows only the columns of the Employees table, which are common to that table and to those that inherit from it. If we want to find out how many words per minute someone types, we must address that query specifically to the Secretaries table:


atf=# select * from secretaries;
id first_name last_name email_address words_per_minute
----+------------+-----------+----------------+------------------
3 Condoleezza Rice rice@state.gov 10
(1 row)


Notice that the id column for all three tables, which was defined as SERIAL (that is, a nonrepeating incrementing integer), is unique across all three tables.


Polymorphic Associations

The way that PostgreSQL has integrated this type of object hierarchy into its relational system is impressive, flexible and useful. And yet, because it is unique to PostgreSQL, it means that no higher-level, database-agnostic application framework can support it. This especially is true in Ruby on Rails, which tries to treat all databases as similar or identical, going so far as to encourage programmers to use a Ruby-based domain-specific language (migrations) to create and modify database definitions. Using PostgreSQL's inheritance features might work, but it will take a fair amount of twisting to make it compatible with Rails.

Besides, Rails already has a feature, known as polymorphic associations, that lets us work with distinct types of items as if they were part of a single class. This isn't the same as an object hierarchy—we can't say that secretaries and programmers are both types of employees. But, we can say that secretaries and programmers are both employable and treat them as similar via that description.

To begin, you might remember that Rails has something known as associations, which allow us to connect one model to another. For example, let's say that each company has one or more employees. Thus, we can create some simple models. We can generate migrations with:

./script/generate model company name:string
./script/generate model employee first_name:string
last_name:string email_address:string company_id:integer

Then, we can turn the automatically generated migration files into actual database tables with the following:

rake db:migrate

Now, we can indicate that each company can have one or more employees by modifying the model files. For example, we add the following to employee.rb:


class Company < xyz =" Company.create(:name"> 'XYZ Corporation')

george = Employee.create(:first_name => 'George',
:last_name => 'Washington',
:email_address => 'georgie@whitehouse.gov',
:company_id => xyz.id)


Now, we can say:

p xyz.employees.first

and we get back our george user. Similarly, we can say:

p george.company

and get back our xyz company. This is all standard stuff for Rails programmers, and it is part of the ActiveRecord feature known as associations. You can create all sorts of associations, giving them arbitrary names. For example, we could say:


class Company < class_name =""> 'Employee',
:conditions => "first_name ilike '%a%'"
end


With this in place, and after restarting the console (or typing reload!), we now can say:

xyz = Company.find_by_name('XYZ Corporation')

xyz.employees_with_a

This prints the empty list—not surprising, given that we have defined only a single employee so far, and his name didn't contain an a. But, now we can create a second employee:


jane = Employee.create(:first_name => 'Jane',
:last_name => 'Austin',
:email_address => 'jane@bookauthor.com',
:company_id => xyz.id)


If we run our association again:

xyz.employees_with_a

now we get our jane employee.

This is all well and good, but what happens if we want to represent different types of employees, each of whom is employed by a company, but with different associated data? This is where polymorphic associations become useful. In order for this to work, we need to change the definitions of our models, as well as the relationships among them (if you're playing along at home, blow away the existing Employee and Company models before continuing):

./script/generate model company name:string
./script/generate model contract employable_id:integer
employable_type:string company_id:integer
./script/generate model programmer main_language:string
first_name:string last_name:string email_address:string
./script/generate model secretary words_per_minute:integer
first_name:string last_name:string email_address:string

The above invocations of script/generate create four different models: one for a company, another for a programmer, another for a secretary and a fourth for a contract. Our PostgreSQL model allowed us to have a single Employee table and to have programmers and secretaries inherit from that table. Rails doesn't let us specify that one model inherits from another. Rather, we use Rails to describe the relationships among the models. Companies are connected to programmers and secretaries via employment contracts.

Because we are looking at the relationships among standalone models, rather than an inheritance hierarchy, there's no obviously good place in which to stick attributes that are common to programmers and secretaries. In the end, I decided to put the attributes in the programmer and secretary models, respectively, despite the repetition.

Now, let's define the associations:


class Company < polymorphic =""> true
end

class Programmer < as =""> :employable
has_many :companies, :through => :contracts
end

class Secretary < as =""> :employable
has_many :companies, :through => :contracts
end


In other words, each company has many contracts. Each contract joins together a company and someone who is employable. Who is employable? Right now, only programmers and secretaries fit the bill, connecting to the employable interface with contracts, and then to a company via a contract.

Behind the scenes, Rails is pulling a nasty trick, one that should make any good database programmer feel sick. The contract model includes two fields (employable_id and employable_type), which point to a single row in a particular table. In some ways, this is sort of a poor man's foreign key. But the difference is that the foreign key can point to any of several tables. And, of course, there is no error checking; only the application can stop me from entering a random text string in the employable_type column.

So, now we can create some relationships:


xyz = Company.create(:name => 'XYZ Corporation')

p1 = Programmer.create(:first_name => 'Linus',
:last_name => 'Torvalds',
:email_address => 'torvalds@osdl.org',
:main_language => 'C')

Contract.create(:employable => p1, :company => xyz)

s1 = Secretary.create(:first_name => 'Condoleezza',
:last_name => 'Rice',
:email_address => 'rice@state.gov',
:words_per_minute => 90)

Contract.create(:employable => s1, :company => xyz)


That's already pretty remarkable. Because both programmers and secretaries are employable (as they both expose the employable interface to the contracts model, using has_many :as), we can join each of them to an instance of the contract model.

But, it gets better, if we add a few more associations:


class Contract < polymorphic =""> true

belongs_to :programmer,
:class_name => 'Programmer', :foreign_key => 'employable_id'
belongs_to :secretary,
:class_name => 'Secretary', :foreign_key => 'employable_id'
end

class Company < through =""> :contracts,
:source => :programmer,
:conditions => "contracts.employable_type = 'Programmer' "

has_many :secretaries, :through => :contracts,
:source => :secretary,
:conditions => "contracts.employable_type = 'Secretary' "

end


With this in place, we now have a complete bidirectional association between programmers and secretaries on one side and companies on the other. Thus, we can say:


>> xyz.programmers
=> [#]

>> xyz.secretaries
=> [#]


But, we also can say:


>> Programmer.find(1).companies
=> [#]


Moreover, we can iterate over xyz.contracts, bringing together the secretaries and programmers models into one package:

>> xyz.contracts.each {c puts c.employable.first_name}
Linus
Condoleezza

Although Rails does not provide inheritance within the models, polymorphic associations make it possible to come close to such functionality. You also get a bunch of convenience functions that make it more natural to work with these additional attributes.

Conclusion
Not all data fits cleanly into two-dimensional tables. When this occurs, you can try to shoehorn your data into an inappropriate container. Or, you can try to use the help that is built in to one or more levels of your software stack. If you use PostgreSQL, inheritance can be really useful. If you use Rails, you can take advantage of polymorphic associations, allowing you to treat two or more models with a common API as similar. This isn't the sort of thing you'll do each day, but it's a useful skill to have on hand for cases when you need to take unusual data.

Resources

To learn how PostgreSQL allows for inheritance, read the on-line manual at www.postgresql.org/docs/8.3/static/ddl-inherit.html.

Rails Cookbook, by Rob Orsini, and published by O'Reilly, has some good information about polymorhphic associations.

The Rails Wiki has some good examples and descriptions of polymorhphic associations at wiki.rubyonrails.org/rails/pages/UnderstandingPolymorphicAssociations.

Reuven M. Lerner, a longtime Web/database developer and consultant, is a PhD candidate in learning sciences at Northwestern University, studying on-line learning communities. He recently returned (with his wife and three children) to their home in Modi'in, Israel, after four years in the Chicago area.

__________________________


Taken From: Linux Journal Issue #173, September 2008

Monday, September 29, 2008

Extract Cab Files From EXE - Pocket PC

Hi there,

I recently bougth a HTC Diamond, which unfortunately is not linux based.

I started to download some aplications and noticed that many off them were exe files for Windows XP or Vista, so i had to use Windows XP or Vista via Active Sync to install them, and that some were cab which i could copy to my PDA via Windows or Linux if when i pluged in the usb cable i select the disk option an not active sync, which made my PDA apear as a USB Pen Drive.

Later on e noticed that the Windows XP or Vista exe, only copied a cab file and executed.
So i tried to find were did the cab was and found that the cab file was temporaly in:

Windows\AppMgr\Install

so i thougth that i could catch the cab rigth before installing it, and i succeded.


Basicly what i did was to execute the exe in Windows Xp, them PDA asked if i wanted to install the cab that the exe on Windows XP tranfered i said yes, and that's when you reach the below screen




Now i hit the home button on the PDA to select the file explorer in order to copy the cab, that is temporarily at Windows\AppMgr\Install to another location on PDA, so that you can store it on your PC so that when you want to install it i can do it from linux.

So i selected the explorer as shown bellow.





And went to Windows\AppMgr\Install where the cab was temporarily and copied it to another location on my PDA and canceled the install process in the first picture, but if you wan you can install.

I have tried to copy the cab before the screen on the first picture when it asks if you want to install, but it keep disapering, and the instalation being canceled.

And thats it! Happy Cab Hunt!

Monday, August 18, 2008

Cfengine - Configuration Management for Multiple Machine

Cfengine for Enterprise Configuration Management

April 1st, 2008 by Scott Lackey

Cfengine makes it easier to manage configuration files across large numbers of machines.

Cfengine is known by many system administrators to be an excellent tool to automate manual tasks on UNIX and Linux-based machines. It also is the most comprehensive framework to execute administrative shell scripts across many servers running disparate operating systems. Although cfengine is certainly good for these purposes, it also is widely considered the best open-source tool available for configuration management. Using cfengine, sysadmins with a large installation of, say, 800 machines, can have information about their environment quickly that otherwise would take months to gather, as well as the ability to change the environment in an instant. For an initial example, if you have a set of Linux machines that need to have a different /etc/nsswitch.conf, and then have some processes restarted, there's no need to connect to each machine and perform these steps or even to write a script and run it on the machines once they are identified. You simply can tell cfengine that all the Linux machines running Fedora/Debian/CentOS with XGB of RAM or more need to use a particular /etc/nsswitch.conf until a newer one is designated. Cfengine can do all that in a one-line statement.

Cfengine's configuration management capabilities can work in several different ways. In this article, I focus on a make-it-so-and-keep-it-so approach. Let's consider a small hosting company configuration, with three administrators and two data centers (Figure 1).

Figure 1. How the Few Control the Many

Each administrator can use a Subversion/CVS sandbox to hold repositories for each data center. The cfengine client will run on each client machine, either through a cron job or a cfengine execution dæmon, and pull the cfengine configuration files appropriate for each machine from the server. If there is work to be done for that particular machine, it will be carried out and reported to the server. If there are configuration files to copy, the ones active on the client host will be replaced by the copies on the cfengine server. (Cfengine will not replace a file if the copy process is partial or incomplete.)

A cfengine implementation has three major components:

  • Version control: this usually consists of a versioning system, such as CVS or Subversion.

  • Cfengine internal components: cfservd, cfagent, cfexecd, cfenvd, cfagent.conf and update.conf.

  • Cfengine commands: processes, files, shellcommands, groups, editfiles, copy and so forth.

The cfservd is the master dæmon, configured with /etc/cfservd.conf, and it listens on port 5803 for connections to the cfengine server. This dæmon controls security and directory access for all client machines connecting to it. cfagent is the client program for running cfengine on hosts. It will run either from cron, manually or from the execution dæmon for cfengine, cfexecd. A common method for running the cfagent is to execute it from cron using the cfexecd in non-dæmon mode. The primary reason for using both is to engage cfengine's logging system. This is accomplished using the following:

*/10 * * * * /var/cfengine/sbin/cfexecd -F

as a cron entry on Linux (unless Solaris starts to understand */10). Note that this is fairly frequent and good only for a low number of servers. We don't want 800 servers updating within the same ten minutes.

The cfenvd is the “environment dæmon” that runs on the client side of the cfengine implementation. It gathers information about the host machine, such as hostname, OS and IP address. The cfenvd detects these factors about a host and uses them to determine to which groups the machine belongs. This, in effect, creates a profile for each machine that cfengine uses to determine what work to perform on each host.

The master configuration file for each host is cfagent.conf. This file can contain all the configuration information and cfengine code for the host, a subset of hosts or all hosts in the cfengine network. This file is often just a starting point where all configurations are stored in other files and “imported” into cfagent.conf, in a very similar fashion to Nagios configuration files. The update.conf file is the fundamental configuration file for the client. It primarily just identifies the cfengine server and gets a copy of the cfagent.conf.

Figure 2. Automated Distribution of Cfengine Files

The update.conf file tells the cfengine server to deploy a new cfagent.conf file (and perhaps other files as well) if the current copy on the host machine is different. This adds some protection for a scenario where a corrupt cfagent.conf is sent out or in case there never was one. Although you could use cfengine to distribute update.conf, it should be copied manually to each host.

Cfengine “commands” are not entered on the command line. They make up the syntax of the cfengine configuration language. Because cfengine is a framework, the system administrator must write the necessary commands in cfengine configuration files in order to move and manipulate data. As an example, let's take a look at the files command as it would appear in the cfagent.conf file:

files:

/etc/passwd mode=644
owner=root action=fixall
/etc/shadow mode=600
owner=root action=fixall

This would set all machines' /etc/passwd and /etc/shadow files to the permissions listed in the file (644 and 600). It also would change the owner of the file to root and fix all of these settings if they are found to be different, each time cfengine runs. It's important to keep in mind that there are no group limitations to this particular files command. If cfengine does not have a group listed for the command, it assumes you mean any host. This also could be written as:

files:
any::
/etc/passwd mode=644
owner=root action=fixall
/etc/shadow mode=600
owner=root action=fixall

This brings us to an important topic in building a cfengine implementation: groups. There is a groups command that can be used to assign hosts to groups based on various criteria. Custom groups that are created in this way are called soft groups. The groups that are filled by the cfenvd dæmon automatically are referred to as hard groups. To use the groups feature of cfengine and assign some soft groups, simply create a groups.cf file, and tell the cfagent.conf to import it somewhere in the beginning of the file:

import:
any::
groups.cf

Cfengine will look in the default directory for the groups.cf file in /var/cfengine/inputs. Now you can create arbitrary groups based on any criteria. It is important to remember that the terms groups and classes are completely interchangeable in cfengine:

groups:
development = ( nfs01 nfs02 10.0.0.17 )
production = ( app01 app02 !development )

You also can combine hard groups that have been discovered by cfenvd with soft groups:

groups:
legacy = ( irix compiled_on_cygwin sco )

Let's get our testing setup in order. First, install cfengine on a server and a client or workstation. Cfengine has been compiled on almost everything, so there should be a package for your OS/distribution. Because the source is usually the latest version, and many versions are bug fixes, I recommend compiling it yourself. Installing cfengine gives you both the server and client binaries and utilities on every machine, so be careful not to run the server dæmon (cfservd) on a client machine unless you specifically intend to do that. After the install, you should have a /var/cfengine/ directory and the binaries mentioned previously.

Before any host can actually communicate with the cfengine server, keys must be exchanged between the two. Cfengine keys are similar to SSH keys, except they are one-way. That is to say, both the server and the client must have each other's public key in order to communicate. Years of sysadmin paranoia cause me to recommend manually copying all keys and trusting nothing. Copy /var/cfengine/ppkeys/localhost.pub from the server to all the clients and from the clients to the server in the same directory, renaming them /var/cfengine/ppkeys/root-10.11.0.1.pub, where the IP is 10.11.0.1.

On the server side, cfservd.conf must be configured to allow clients to access particular directories. To do this, create an AllowConnectionsFrom and an admit section:

#cfservd.conf

control:
AllowConnectionsFrom = ( 192.168.0.0/24 )
admit:
/configs/datacenter1 *.example1.com
/configs/datacenter2 *.example2.com

To test your example client to see whether it is connecting to the cfengine server, make sure port 5803 is clear between them, and run the server with:

cfservd -v -d2

And, on the client run:

cfagent -v --no-splay

This will give you a lot of debugging information on the server side to see what's working and what isn't.

Now, let's take a look at distributing a configuration file. Although cfengine has a full-featured file editor in the editfiles command, using this method for distributing configurations is not advised. The copy command will move a file from the server to the client machine with .cfnew appended to the filename. Then, once the file has been copied completely, it renames the file and saves the old copy as .cfsaved in the specified directory. Here's the copy command syntax:

copy:
class::
<>

dest=target-file
server=server
mode=mode
owner=owner
group=group
backup=true/false
repository=backup dir
recurse=number/inf/0
define=classlist

Only the dest= is required, along with the filename to save at the destination. These can be different. Here's another example:

copy:
linux::
${copydir}/linux/resolv.conf

dest=/etc/resolv.conf
server=cfengine.example1.com
mode=644
owner=root
group=root
backup=true
repository=/var/cfengine/cfbackup
recurse=0
define=copiedresolvdotconf

The last line in this copy statement assigns this host to a group called copiedresolvdotconf. Although we don't have to do anything after copying this particular file, we may want to do some action on all hosts that just had this file successfully sent to them, such as sending an e-mail or restarting a process. As another example, if you update a configuration file that is attached to a dæmon, you may want to send a SIGHUP to the process to cause it to reread the configuration file. This is common with Apache's httpd.conf or inetd.conf. If the copy is not successful, this server won't be added to the copiedresolvdotconf class. You can query all servers in the network to see whether they are members and, if not, find out what went wrong.

A great way to version control your config files is to use a cfengine variable for the filename being copied to control which version gets distributed. Such a line may look something like this:

copy:
linux::
${copydir}/linux/${resolv_conf}

Or, better yet, you can use cfengine's class-specific variables, whose scope is limited to the class with which they are associated. This makes copy statements much more elegant and can simplify changes as your cfengine files scale:

control:

# ${resolve_conf} value depends on context,
# is this a linux machine or hpux?
linux:: resolve_conf = ( "${copydir}"/linux/resolv.conf )
hpux:: resolve_conf = ( "${copydir}"/hpux/resolv.conf )
copy:
linux::

${resolve_conf}

Here is a full cfagent.conf file that makes use of everything I've covered thus far. It also adds some practical examples of how to do sysadmin work with cfengine:

# cfagent.conf

control:
actionsequence = ( files editfiles processes )
AddInstallable = ( cron_restart )
solaris:: crontab = ( /var/spool/cron/crontabs/root )
linux:: crontab = ( /var/spool/cron/root )

files:
solaris::
${crontab}
action=touch
linux::
${crontab}
action=touch

editfiles:
solaris::
{ ${crontab}
AppendIfNoSuchLine "0,10,20,30,40,50 * * * *
↪/var/cfengine/sbin/cfexecd -F"
DefineClasses "cron_restart"
}
linux::
{ ${crontab}
AppendIfNoSuchLine "0,10,20,30,40,50 * * * *
↪/var/cfengine/sbin/cfexecd -F"
#linux doesn't need a cron restart.
}

shellcommands:
solaris.cron_restart::
"/etc/init.d/cron stop"
"/etc/init.d/cron start"

import:
any::
groups.cf
copy.cf

The above is a full cfagent configuration that adds cfengine execution from cron to each client (if it's Linux or Solaris). So effectively, once you run cfengine manually for the first time with this cfagent.conf file, cfengine will continue to run every five minutes from that host, but you won't need to edit or restart cron. The control section of the cfagent.conf is where you can define some variables that will control how cfengine handles the configuration file. actionsequence tells cfengine what order to execute each command, and AddInstallable is a variable that holds soft groups that get defined later in the file in a “define” statement, such as after the editfiles command where the line is DefineClasses "cron_restart". The reason for using AddInstallable is sometimes cfengine skips over groups that are defined after command execution, and defining that group in the control section ensures that the command will be recognized throughout the configuration.

Being able to check configuration files out from a versioning system and distribute them to a set of servers is a powerful system administration tool. A number of independent tools will do a subset of cfengine's work (such as rsync, ssh and make), but nothing else allows a small group of system administrators to manage such a large group of servers. Centralizing configuration management has the dual benefit of information and control, and cfengine provides these benefits in a free, open-source tool for your infrastructure and application environments.

Scott Lackey is an independent technology consultant who has developed and deployed configuration management solutions across industry from NASA to Wall Street. Contact him at slackey@violetconsulting.net, www.violetconsulting.net.