ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


Big Scary Daemons

Stable SMB

11/15/2001

I discussed FreeBSD's SMB filesystem support well over a year ago. At the time, it was highly experimental and suffered occasional seizures.

It has since improved to the point where it is reliable enough for use in production settings. If you want to access a Windows share from your FreeBSD workstation, this is how you do it. Before you start, gather some basic information about your Windows network.

The first problem you have is supporting the multiple character sets so common in Windows. It's very easy for a Windows user to use characters not found in the standard ASCII alphabet. You don't want to dump such a character into your kernel; you'll only confuse it, and a confused kernel is not a happy kernel. The FreeBSD kernel does not include the libraries to handle this. Install the libiconv port from /usr/ports/converters/libiconv before you proceed. Note that libiconv is under the LGPL; if you're interested in using SMBFS in an embedded system, run this by your legal department.

Now recompile your kernel to handle SMB. Just add the following options to your kernel.

options         NETSMB
options         NETSMBCRYPTO
options         LIBMCHAIN
options         LIBICONV
options	        SMBFS

The SMBFS kernel option is also available as a module. Because you already must rebuild your kernel to include SMB networking support, however, you might as well compile it statically.

Once you have the kernel built, install the SMB tools from /usr/ports/net/smbfs. The SMB tools must be exactly synchronized with your kernel. This makes packages mostly useless, unless you have several identical machines. If you upgrade your FreeBSD install, you must upgrade the port. To make life somewhat more difficult, the master SMBFS source code repository lurks behind a very slow link in Kazakhstan. I recommend that you store the distribution file somewhere on your network, so you can easily rebuild the tools without having to re-fetch the source from the other side of the world.

The SMB tools use a configuration file, either $HOME/.nsmbrc or /usr/local/etc/nsmb.conf. Any settings in nsmb.conf override settings in user home directories. The configuration file is divided into sections by labels in angle brackets. For example, settings that apply to every SMB connection are kept in the [default] section. You can create your own sections by specifying servers, users, and share, in one of the following formats.

[servername]
[servername:username]
[servername:username:sharename]

For example, information that applies to an entire server goes in a section named after the server. Information that applies to a specific user is kept in a user name section, and information that only applies to a single share is kept in a label that includes the share name. You could lump the information for all the shares under a [servername] entry if you don't have more specific information per share.

These values are all SMB values -- i.e., my Windows user name is "mlucas", but my Unix user name is "mwlucas", so I use "mlucas" in nsmb.conf.

You use keywords to assign a configuration to a section. Some keywords can only be used in particular sections. For example, servers have IP addresses, users don't. You assign a value with an equal sign, such as "keyword=value". Here are the keywords.

workgroup=string

This is the name of the NT domain or Windows workgroup you want to access.

addr=a.b.c.d

This is the IP (or IPX) address of a SMB server with this name. This can only appear under a plain [servername] label.

charsets local:remote

This handles conversions between the character set used on the FreeBSD system and the character set used on the SMB server. (As SMBFS was written in Central Asia, this was a matter of no small concern!)

nbns=a.b.c.d

This is the IP address of the NetBIOS (WINS) name server. You can put this in the [default] section or under a particular [servername].

nbscope=string

This is the NetBIOS scope. If you don't know what NetBIOS scope is, you probably don't need to set it.

retry_count

This is the number of times the SMB client will try to contact the server before assuming that the connection has broken. The default is probably fine.

timeout

This is the length of time the system will wait for a response to a SMB request. Again, the default is probably fine.

password=string

This is a clear-text password for a user or a share. If you must store passwords in nsmb.conf, be sure that only root can read the file. Storing a password in $HOME/.nsmbrc is a bad idea on a multi-user system. You can scramble this password by running smbutil -crypt. The scrambled password will have double dollar signs ($$) in front of it. This will help prevent someone accidentally seeing the password, but it can be easily unscrambled by a malicious user.

So, let's start setting up a basic nsmb.conf file. First, we want to be able to find hosts. For this we need a workgroup and a NetBIOS name server. I also have the same user name across the entire domain, so I'm going to put my user name in the [default] section.

[default]
workgroup=EXAMPLE
nbns=192.168.2.80
username=mlucas

With this information, you should be able to perform basic SMB name queries. smbutil(1) can perform basic NetBIOS name resolution.

# smbutil lookup fileserv4
Got response from 192.168.2.80
IP address of fileserv4: 192.168.1.202
#

If this works, you have basic SMB functionality. Now we want to access a share on that system. Before you can query a host, you must log in to it. Only root can use these smbutil functions.

# smbutil login //mlucas@fileserv4
Password:
Connected to MLUCAS
#

So, our password is correct. Let's see what resources this server offers.

# smbutil view //mlucas@fileserv4
Password:
Share        Type       Comment
-------------------------------
jsmith$    disk       
gdonner$   disk       
mlucas$    disk
...

You'll get a list of every shared resource on the SMB server. When finished, log out of the host.

# smbutil logout //mlucas@fileserv4
Password:
Connection unmarked as permanent and will 
be closed when possible
#

Now that you've finished investigating, let's actually mount a share with mount_smbfs(8). The syntax is very simple.

mount_smbfs //username@servername/share /mount/point

To mount my personal fileserver share on /home/mwlucas/smbmount, I would do:

# mount_smbfs //mlucas@fileserv4/mlucas /home/mwlucas/smbmount

Check your work with df(1).

#df
Filesystem              1K-blocks    Used   Avail Capacity  
Mounted on
/dev/ad0s1a                 99183   49105   42144  54%  /
/dev/ad0s1f               5186362 3091500 1679954  65%  /usr
/dev/ad0s1e                198399   22816  159712  12%  /var
procfs                          4       4       0 100%  /proc
//MLUCAS@FILESERV4/MLUCAS  128000   54320   73680  42%    
/usr/home/mwlucas/smbmount
#

I can now do basic file operations, including using emacs and StarOffice on the documents in this folder. Life just got a little better. mount_smbfs includes several options to fine-tune the mount behavior, however. We can customize the nsmb.conf file to use different user names to access different shares, or to bypass NetBIOS name resolution for particular hosts. Here's a more complicated example, with comments.

[default]
workgroup=EXAMPLE
nbns=192.168.2.80
username=mlucas

#I have a share on my desktop with a separate password
[desktop:mlucas]
password=$$1725a5038393e12ee

#development is in a different NT domain, with 
#a shared username
[development]
workgroup=EXAMPLE2
username=support

Ownership of files across these systems can be problematic. Your Unix user names probably don't map to Windows user names, and Unix has a different permissions scheme. Because you're using a single Windows user name to access the share, you have whatever access that account has to the Windows resources. You should assign the proper Unix permissions for that share, however. By default, mount_smbfs assigns the new share the same permissions as the mount point used. The directory /home/mwlucas/smbmount in our example is owned by "mwlucas", in the group "mwlucas", and has mode 755. I can edit what's in this directory, but no other users can. You can use mount_smbfs's -f option to choose a different mode, and the -d option to choose a different directory mode. For example, to set it so only I could access the contents of this directory I would use mount_smbfs -d 700. (This would make the Unix permissions far more stringent than the Windows ones, but that's not my concern at the moment.) I can even change the owner with the -u option, and the group with the -g option.

The -I option tells mount_smbfs to skip NetBIOS name resolution, and instead use the host name or IP address provided on the command line.

-N means that mount_smbfs should read the password from the configuration file, and not prompt for a password. This means that you need to have your clear-text password in nsmb.conf.

The -W flag specifies a new workgroup. It overrides any settings in nsmb.conf.

Windows is case-insensitive; Unix is case-sensitive. SMBFS defaults to leaving the case as it finds it, but this is not necessarily what you want. The -c flag tells mount_smbfs to change the case. -c l changes everything to lowercase, while -c u changes everything to uppercase.

In working with mount_smbfs, I've found it flexible enough to handle almost any situation on a Windows network. This allows you to use your FreeBSD system seamlessly with the rest of the office.

Michael W. Lucas


Read more Big Scary Daemons columns.

Return to the BSD DevCenter.

Copyright © 2009 O'Reilly Media, Inc.