Samba Logging for Audit Trails

by Edward Kablaoui

We at Northrop Grumman recently decided to replace the Microsoft Windows 2000 server on one of our networks with a Linux server running Samba. The primary motivations for replacing the Windows server with Linux were:

  • Common user names and passwords for both Windows and Linux users.

  • Export commonly shared directories and files using NFS and Samba.

  • Allow software developers the freedom to choose their development environment.

  • No additional licensing fees required for Windows 2000 server and clients.

  • Centralized and cleaner audit trails.

  • A more secure computing environment.

  • Software upgrades can be scheduled when necessary as opposed to being dictated by outside software vendors.

In addition to configuring Samba as a primary domain controller, modifications were made to the Samba source code to meet the security requirements of our network. This article briefly describes how to install and configure Samba and then explains in detail how to modify Samba source code to produce log entries required for audit trails.

Audit Trail Requirements

Our networks must be configured to meet corporate and customer requirements regarding security. Among the various security requirements that must be met, administrators need to have the ability to audit activity on the network. The required information gathered and logged for these audits is referred to as an audit trail and include the following information: successful logins, logouts, failed logins and password changes.

Most operating systems generate log files with this information, but it may be scattered in a number of different files and contain more information than is necessary. We also wanted to centralize this information so network administrators do not have to examine the logs on every computer on the network. Configured properly, a Windows 2000 server logs the above information for all machines connected to the network, in addition to reporting a myriad of extraneous information. This additional information makes security audits longer, more error-prone and also occupies a lot of disk space when archived.

In order to use Linux and Samba as the primary domain server for Windows 2000 clients, Samba has to duplicate the logging capabilities of the Windows 2000 server. Once Samba was configured for the network, it seemed the only way to meet the logging requirements was to modify the Samba source code. An additional benefit of modifying the source code was the ability to have only the necessary information recorded in the log files. The replacement of the Windows 2000 server with Samba would not have been possible had Samba been a closed-source, proprietary product.

Downloading and Configuring Samba

The Linux server initially arrived with Red Hat 8.0 and Samba already installed. The first step was to download the tarred and compressed version of Samba 2.2.8a from the Web site, www.samba.org. Once downloaded, Samba was installed by running the following commands as root:

tar cvfz samba-2.2.8a.tar.gz
cd samba-2.2.8a/source
./configure
make
make install

The Samba executables, smbd and nmbd, were installed under the /usr/local/samba/bin directory. The Red Hat installation had placed these executables under the /sbin directory. Using the newly created Samba executables requires changing the Samba startup script /etc/init.d/samba. The current Samba dæmons should be stopped first by running the command /etc/init.d/samba stop.

The /etc/init.d/samba file then is edited such that the commands for starting smbd and nmbd are changed from /sbin/smbd -D to /usr/local/samba/bin/smbd -D and /sbin/nmbd -D to /usr/local/samba/bin/nmbd -D. The new dæmons are then started with the command /etc/init.d/samba start.

Once the new dæmons are installed successfully, Samba needs to be configured by setting parameters in the smb.conf file. For the 2.2.8a distribution, the default location of this file is /etc/samba. The smb.conf file consists of sections denoted by square brackets, and each section names a share or service. The following example shows some of the parameter values set under the global section to create a Primary Domain Controller for Windows clients:

[global]
netbios name = SambaServer
workgroup     =  NETDOMAIN
domain master = yes
local master = yes
preferred master =yes
os level =  65

For authenticating users on the network, the following parameters also need to be set under the global section:

encrypt passwords = yes
security = user
domain logons = yes

Finally, for Windows 2000 clients, the domain admin group and add user script global parameters need to be set as well:

domain admin group = root
add user script = /usr/sbin/useradd -d /dev/null \
                    -g 100 -s /bin/false -M %u

Public and private shares for Window clients are created by adding new sections.

Public:

[share]
path = /home/share
read only = no
browseable = yes
guest ok = no
create mode = 0770
comment = Shared Folder
hide dot files = yes

Private:

[homes]
path = /home/%u
read only = no
browseable = no
guest ok = no
map archive = yes
create mode = 0750
comment = Home Directories
hide dot files = yes

To verify that the parameters are correct in the smb.conf file or to debug configuration problems, use the testparm command. For debugging problems with Samba in general, the log files log.smbd and log.nmbd under the /var/log/samba directory are invaluable. The parameter log level in the global section of the smb.conf file determines the amount of detailed information Samba writes to the log files, with level 0 being the most general and 10 being the most detailed. Each logging level contains the messages from that level, in addition to the logging messages below it. For example, a logging level of 5 contains messages from level 5, plus those from levels 0 through 4.

Listing 1 is an example from the log.smbd file. The first line in a typical entry in the log file contains the date and time the event occurred, the source file name, the function name and the line number where the message was generated. The second line contains the action that occurred, the domain and client name and a short message describing the logging event. Later in this article, we examine how these messages are generated in the Samba source code.

Listing 1. Log Entries from /var/log/samba/log.smbd

[2003/11/25 17:13:12, 0] smbd/server.c:main(791)
    smbd version 2.2.8a started.
  Copyright Andrew Tridgell and the \
    Samba Team 1992-2002
[2003/11/25 17:17:32, 0] \
    rpc_server/srv_netlog_nt.c:_net_sam_logon(643)
  Logon . Domain:[NETDOMAIN].\
    HostName:[192.168.0.15]. \
    User:[john]. FAILED No Such User
[2003/11/25 17:17:55, 0] \
    rpc_server/srv_netlog_nt.c:_net_sam_logon(665)
  Logon . Domain:[NETDOMAIN]. \
    HostName:[192.168.0.15]. \
    User:[bill]. FAILED Incorrect Password
[2003/11/25 17:18:33, 0] \
    rpc_server/srv_netlog_nt.c:_net_sam_logon(691)
  Logon . Domain:[NETDOMAIN]. \
    HostName:[192.168.0.15] \
    User:[bill] Successfully Logged On
[2003/11/25 17:19:34, 0] \
    smbd/chgpasswd.c:check_oem_password(836)
  check_oem_password: incorrect password length \
    (262218674) for user bill.
[2003/11/25 17:19:46, 0] \
    smbd/chgpasswd.c:chgpasswd(474)
  Password Change: user bill, \
    New password is shorter than minimum password \
    length = 8
[2003/11/25 17:21:29, 0] \
    smbd/chgpasswd.c:chat_with_program(450)
  Password Change . User:[bill] \
    Password Successfully Changed
[2003/11/25 17:16:58, 0] \
    smbd/service.c:close_cnum(680)
  clientPC (192.168.0.15) \
    closed connection to service bill

Users can be added to the domain by running the command smbpasswd -a username as root and setting the user password. The passwords are stored in the /etc/samba/private/smbpasswd file. Users also can be disabled with the command smbpasswd -d and enabled by running smbpasswd -e.

For more details on configuring Samba for Windows 2000 clients and understanding SMB protocols, O'Reilly's Using Samba, Second Edition, by Jay Ts, Robert Eckstein and David Collier-Brown, is an excellent reference.

Modifying Samba Source Code for Audit Trails

Once the network was configured and working properly, the next step was to record the required information for the audit trails in the log.smbd file. Initially, this was attempted by setting various logging levels in the smb.conf file, restarting the Samba dæmons by executing /etc/init.d/samba restart and then analyzing the output from the log files while performing various tasks on a Windows 2000 client. Unfortunately, regardless of the log level, none of the required information was being logged. At this point, it became obvious that modifications to the source code were necessary to generate the log entries.

The Samba source code is in the samba-2.2.8a/source directory and is the root directory for the filename in the log messages. The first entry in Listing 1 shows the file as smbd/server.c:main(791). By examining line 791 in the samba-2.2.8a/source/smbd/server.c file, you can see the DEBUG macro is used to generate the log message. The syntax for the DEBUG macro is:

DEBUG(log_level, "string", arguments);

The format for the second and third arguments is similar to the printf function. Examples of custom DEBUG statements are shown in Listings 2 through 4.

Listing 2. DEBUG Calls Added to source/rpc_server/srv_netlog_nt.c


632  /* get the account information */
633  pdb_init_sam(&sampass);
634  become_root();
635  ret = pdb_getsampwnam(sampass, nt_username);
636  unbecome_root();
637
638
639  if (!ret)
640  {
641     pdb_free_sam(sampass);
642     // ESK
631  /* checks for failed users */
643     DEBUG(0,("Logon . Domain:[%s]. HostName: \
       [%s]. User:[%s]. FAILED No Such User \n",
             lp_workgroup(),
             client_addr(),
             nt_username));
644     return NT_STATUS_NO_SUCH_USER;
645  }
646
647  acct_ctrl = pdb_get_acct_ctrl(sampass);
630  map_username(nt_username);
.
.
.
663  /* Check for failed password */
664  if (!NT_STATUS_IS_OK(status)) {
665     DEBUG(0,("Logon . Domain:[%s]. HostName: \
   [%s]. User:[%s]. FAILED Incorrect Password \n",
             lp_workgroup(),
             client_addr(),
             nt_username));
666     pdb_free_sam(sampass);
667     return status;
668  }
.
.
.
669 /* Check PAM Password */
670 #ifdef WITH_PAM
671  become_root();
672  status =
   smb_pam_accountcheck(pdb_get_username(sampass));
673  unbecome_root();
674  if (!NT_STATUS_IS_OK(status)) {
675     pdb_free_sam(sampass);
676     DEBUG(0,("Logon . Domain:[%s]. HostName: \
   [%s]. User:[%s]. FAILED Incorrect Password \n",
                lp_workgroup(),
                client_addr(),
                nt_username));
677     return status;
678  }
679 #endif
.
.
.
690   /* Makes it to this point you have
         successfully logged on */
691   DEBUG(0,("Logon . Domain:[%s]. HostName: \
       [%s] User:[%s] Successfully Logged On\n",
                lp_workgroup(),
                client_addr(),
                nt_username));

Listing 3. DEBUG Call Added to source/smbd/service.c


675 // ESK
676 if(strcmp(lp_servicename(SNUM(conn)), \
                                       "share") &&
677    strcmp(lp_servicename(SNUM(conn)), \
                                    "profiles") &&
678    strcmp(lp_servicename(SNUM(conn)),\
                                    "netlogon") &&
679    strcmp(lp_servicename(SNUM(conn)), "IPC$")){
680  DEBUG(0, ("%s (%s) closed connection to \
                                     service %s\n",
681       remote_machine,conn->client_address,
682       lp_servicename(SNUM(conn))));
683   }

Listing 4. DEBUG Call Added to source/smbd/chgpasswd.c


447
448  /* Logs Password Change */
449  if (chstat)
450     DEBUG(0, ("Password Change . User:[%s] \
            %sPassword Successfully Changed\n",
451           name, (chstat ? "" : "un")));
452     return (chstat);
453 }

Creating custom log messages requires inserting DEBUG macros into the appropriate section of code and filling in the correct parameters and messages. Once the DEBUG statements are inserted, the Samba executables need to be rebuilt by executing make install in the samba-2.2.a/source directory; the dæmons are restarted with the command /etc/init.d/samba restart. Any new log messages added to the Samba source files now should appear in the log files.

Determining where DEBUG statements should be placed in the code may require setting various log levels in the smb.conf file. The output of the log files can help narrow down which source files should be examined for particular information. Using printf statements also may help in determining which variables should be logged and in formulating the final log message. If you do plan on using printf statements, smbd and nmbd should be executed without the -D option by stopping the dæmons with the command /etc/init.d/samba stop and executing /usr/local/samba/bin/smbd and /usr/local/samba/bin/nmbd on the command line. The printf statements then are directed toward standard output and appear on the console.

Listings 2 through 4 show custom DEBUG statements added to the Samba source code. Listing 2 shows DEBUG statements added to the source/rpc_server/srv_netlog_nt.c file for reporting failed and successful network logons. The first DEBUG statement reports when an unknown user attempts to log on to the network, and the second DEBUG statement records incorrect passwords. An additional DEBUG statement was added for installations of Samba using PAM. The final DEBUG statement records a successful logon to the network. By examining the log output from Listing 1, you should see a direct correspondence between each of the DEBUG statements and the generated log entries.

Listing 3 shows a DEBUG statement added to the source/smbd/service.c file to capture when a user has logged off the system by checking when a share to the user has been closed. Unfortunately, this is an unreliable check because the user always is dropping shares during the course of a session. There also is a short delay between the time the user logs off the network and when the dropped share is recorded. Determining when a user has logged off the network requires checking any logons to the machine after the last user share was dropped or checking whether the machine still is locked by the user.

Once Samba is logging the required information, you may want to clean up the log file by removing unnecessary entries. This can be accomplished by setting the log level to 0 in required DEBUG statements and setting the log level to 1 or higher for other DEBUG statements. The log level parameter in the smb.conf file then should be set to 0. The logging features of Samba make it easy to track down unwanted log entries by providing the exact location of the DEBUG statement. Cleaning up log.smbd makes the audits easier and less error-prone than a cluttered log file, such as the log file generated by a Windows 2000 server.

Updating User Passwords

When updating passwords, system requirements state that passwords must be at least eight characters long and the password change must be logged. In addition, we also wanted the passwords to be synchronized between Windows and Linux so users have common logins for both systems.

For the first requirement, the define statement in source/include/local.h, on line 175, was changed to #define MINPASSWDLENGTH 8. To ensure this change is captured in all the necessary source files, make clean should be executed in the source directory before executing make install.

The source code for verifying and updating password changes is located in the file source/smbd/chgpasswd.c. Listing 4 shows the DEBUG statement that was added to the end of the chat_with_program function to log when users successfully change their passwords. In addition to adding the capability to record successful password changes, the failed password updates also are logged. Failed password changes are recorded because regardless of why the password update failed, the following message always is returned to the user:

The User name or old password is incorrect.
Letters in passwords must be typed using the
correct case. Make sure the Caps Lock is not
accidentally on.

These log messages can help frustrated users determine why they are unable to update their passwords. However, access to these log messages requires assistance from the system administrator. Log entries 5 and 6 in Listing 1 present two examples of user bill being unable to change his password successfully.

To synchronize passwords between Samba and the Linux system passwords, set the following fields in the smb.conf file under the global section:

[global]
unix password sync = yes
pam password change = yes
passwd program = /usr/bin/passwd
passwd chat =*New*password* %n\n *new*password*
↪%n\n *successfully*

For most systems, the passwd chat field does not need to be set, because the default setting works fine. If the passwd chat field does need to be set, the syntax should follow the passwd command's input and output closely. The syntax for password chat is * for any character and %n for the new password; spaces designate new lines, and \n is used when user input is required. For further help with debugging, set the log level to 101 and the field passwd chat debug to yes in the global section of the smb.conf file. As a last resort, printf and DEBUG statements can be used in the function chat_with_program in the chpasswd.c file to help debug the problem.

Future Work

Some of the current problems mentioned above, such as displaying a more meaningful error message when users fail to update their passwords and a more exact method of determining when users have logged off the network, need to be addressed. Additional features, such as user lockout after five consecutive unsuccessful login attempts and preventing the user from reusing the five previous passwords, also should be added. Using LDAP for both Linux and Windows clients is worth investigating as well.

Conclusion

Samba provides a reasonable alternative to using Windows 2000 servers on a network to manage Windows clients. The primary advantage of Samba over Windows is the ability to modify the Samba source code to create a system tailored for a specific computing need. It also offers network administrators the ability to troubleshoot the network at the source code level. None of this is possible when using proprietary software, a huge drawback in configuring and debugging services on a network. All of these factors add up to large cost savings in both licensing fees and network administration time.

Edward Kablaoui (eskablaoui@yahoo.com) currently is a software engineer at Northrop Grumman. He lives in Maryland with his wife, Nancy.

Load Disqus comments