Samba3 Developers Guide
Samba3 Developers Guide
Jelmer R. Vernooij
Warning
ii
Attribution iii
• Anthony Liguori<mailto:aliguor@us.ibm.com>
• Jelmer Vernooij<mailto:jelmer@samba.org>
Chapter 10, “VFS Modules”
• Alexander Bokovoy<mailto:ab@samba.org>
• Stefan Metzmacher<mailto:metze@samba.org>
Chapter 11, “The smb.conf file”
• Chris Hertel
Chapter 12, “Samba WINS Internals”
• Gerald Carter
Chapter 13, “LanMan and NT Password Encryption”
• Jeremy Allison<mailto:samba@samba.org>
Chapter 14, “Tracing samba system calls”
• Andrew Tridgell
Chapter 15, “Samba Printing Internals”
• Gerald Carter
Chapter 16, “Notes to packagers”
• Jelmer Vernooij
CONTENTS
Contents
ATTRIBUTION ii
v
vi Contents
2.4.5.1 Request 45
2.4.5.2 Response 45
2.5 \\MAILSLOT\NET\NTLOGON 45
2.5.1 Query for PDC 45
2.5.1.1 Request 45
2.5.1.2 Response 46
2.5.2 SAM Logon 47
2.5.2.1 Request 47
2.5.2.2 Response 48
2.6 SRVSVC Transact Named Pipe 48
2.6.1 Net Share Enum 49
2.6.1.1 Request 49
2.6.1.2 Response 49
2.6.2 Net Server Get Info 50
2.6.2.1 Request 50
2.6.2.2 Response 50
2.7 Cryptographic side of NT Domain Authentication 50
2.7.1 Definitions 50
2.7.2 Protocol 51
2.7.3 Comments 52
2.8 SIDs and RIDs 53
2.8.1 Well-known SIDs 53
2.8.1.1 Universal well-known SIDs 53
2.8.1.2 NT well-known SIDs 54
2.8.2 Well-known RIDS 55
2.8.2.1 Well-known RID users 55
2.8.2.2 Well-known RID groups 55
2.8.2.3 Well-known RID aliases 55
Chapter 8 MODULES 80
8.1 Advantages 80
8.2 Loading modules 80
x Contents
The protocol
Chapter 1
1.1 Introduction
This is a short document that describes some of the issues that confront a
SMB implementation on unix, and how Samba copes with them. They may
help people who are looking at unix<->PC interoperability.
It was written to help out a person who was writing a paper on unix to PC
connectivity.
1.2 Usernames
The SMB protocol has only a loose username concept. Early SMB pro-
tocols (such as CORE and COREPLUS) have no username concept at all.
Even in later protocols clients often attempt operations (particularly printer
operations) without first validating a username on the server.
Unix security is based around username/password pairs. A unix box should
not allow clients to do any substantive operation without some sort of vali-
dation.
The problem mostly manifests itself when the unix server is in ”share level”
security mode. This is the default mode as the alternative ”user level”
security mode usually forces a client to connect to the server as the same
user for each connected share, which is inconvenient in many sites.
In ”share level” security the client normally gives a username in the ”session
setup” protocol, but does not supply an accompanying password. The client
then connects to resources using the ”tree connect” protocol, and supplies a
password. The problem is that the user on the PC types the username and
3
4 NetBIOS in a Unix World Chapter 1
The commonly used SMB protocols have no way of saying ”you can’t do
that because you don’t own the file”. They have, in fact, no concept of file
ownership at all.
This brings up all sorts of interesting problems. For example, when you copy
a file to a unix drive, and the file is world writeable but owned by another
user the file will transfer correctly but will receive the wrong date. This is
because the utime() call under unix only succeeds for the owner of the file,
or root, even if the file is world writeable. For security reasons Samba does
all file operations as the validated user, not root, so the utime() fails. This
can stuff up shared development diectories as programs like ”make” will not
get file time comparisons right.
There are several possible solutions to this problem, including username
mapping, and forcing a specific username for particular shares.
1.4 Passwords
Many SMB clients uppercase passwords before sending them. I have no idea
why they do this. Interestingly WfWg uppercases the password only if the
server is running a protocol greater than COREPLUS, so obviously it isn’t
just the data entry routines that are to blame.
Section 1.5. Locking 5
Unix passwords are case sensitive. So if users use mixed case passwords they
are in trouble.
Samba can try to cope with this by either using the ”password level” option
which causes Samba to try the offered password with up to the specified
number of case changes, or by using the ”password server” option which
allows Samba to do its validation via another machine (typically a WinNT
server).
Samba supports the password encryption method used by SMB clients. Note
that the use of password encryption in Microsoft networking leads to pass-
word hashes that are ”plain text equivalent”. This means that it is *VERY*
important to ensure that the Samba smbpasswd file containing these pass-
word hashes is only readable by the root user. See the documentation EN-
CRYPTION.txt for more details.
1.5 Locking
Since samba 2.2, samba supports other types of locking as well. This section
is outdated.
One major problem is that dos locks can be in a 32 bit (unsigned) range.
Unix locking calls are 32 bits, but are signed, giving only a 31 bit range.
Unfortunately OLE2 clients use the top bit to select a locking range used
for OLE semaphores.
To work around this problem Samba compresses the 32 bit range into 31 bits
by appropriate bit shifting. This seems to work but is not ideal. In a future
version a separate SMB lockd may be added to cope with the problem.
It also doesn’t help that many unix lockd daemons are very buggy and
crash at the slightest provocation. They normally go mostly unused in a
unix environment because few unix programs use byte range locking. The
stress of huge numbers of lock requests from dos/windows clients can kill
the daemon on some systems.
6 NetBIOS in a Unix World Chapter 1
When a SMB client opens a file it asks for a particular ”deny mode” to be
placed on the file. These modes (DENY NONE, DENY READ, DENY WRITE,
DENY ALL, DENY FCB and DENY DOS) specify what actions should
be allowed by anyone else who tries to use the file at the same time. If
DENY READ is placed on the file, for example, then any attempt to open
the file for reading should fail.
Unix has no equivalent notion. To implement this Samba uses either lock
files based on the files inode and placed in a separate lock directory or a
shared memory implementation. The lock file method is clumsy and con-
sumes processing and file resources, the shared memory implementation is
vastly prefered and is turned on by default for those systems that support
it.
A SMB session can run with several uids on the one socket. This happens
when a user connects to two shares with different usernames. To cope with
this the unix server needs to switch uids within the one process. On some
unixes (such as SCO) this is not possible. This means that on those unixes
the client is restricted to a single uid.
Note that you can also get the ”trapdoor uid” message for other reasons.
Please see the FAQ for details.
This is enforced in Unix as non-root users can’t open a socket for listening
on port numbers less than 1000.
Most PC based SMB clients (such as WfWg and WinNT) don’t follow this
convention completely. The main culprit is the netbios nameserving on udp
port 137. Name query requests come from a source port of 137. This is
a problem when you combine it with the common firewalling technique of
not allowing incoming packets on low port numbers. This means that these
clients can’t query a netbios nameserver on the other side of a low port
based firewall.
The problem is more severe with netbios node status queries. I’ve found that
WfWg, Win95 and WinNT3.5 all respond to netbios node status queries on
port 137 no matter what the source port was in the request. This works
between machines that are both using port 137, but it means it’s not possible
for a unix user to do a node status request to any of these OSes unless they
are running as root. The answer comes back, but it goes to port 137 which
the unix user can’t listen on. Interestingly WinNT3.1 got this right - it
sends node status responses back to the source port in the request.
There are many ”protocol levels” in the SMB protocol. It seems that each
time new functionality was added to a Microsoft operating system, they
added the equivalent functions in a new protocol level of the SMB protocol
to ”externalise” the new capabilities.
This means the protocol is very ”rich”, offering many ways of doing each
file operation. This means SMB servers need to be complex and large. It
also means it is very difficult to make them bug free. It is not just Samba
that suffers from this problem, other servers such as WinNT don’t support
every variation of every call and it has almost certainly been a headache for
MS developers to support the myriad of SMB calls that are available.
There are about 65 ”top level” operations in the SMB protocol (things like
SMBread and SMBwrite). Some of these include hundreds of sub-functions
(SMBtrans has at least 120 sub-functions, like DosPrintQAdd and NetSes-
sionEnum). All of them take several options that can change the way they
work. Many take dozens of possible ”information levels” that change the
structures that need to be returned. Samba supports all but 2 of the ”top
8 NetBIOS in a Unix World Chapter 1
NT DOMAIN RPC’S
2.1 Introduction
9
10 NT Domain RPC’s Chapter 2
<http://mailhost.cb1.com/~lkcl/crypt.html>
<http://samba.org/cgi-bin/mfs/01/digest/1997/97aug/0391.html>
<http://mailhost.cb1.com/~lkcl/crypt.txt>
HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters
Incorrect direct editing of the registry can cause your machine to fail. Then
again, so can incorrect implementation of this protocol. See ”Liability:”
above.
Bear in mind that each packet over-the-wire will have its origin in an API
call. Therefore, there are likely to be structures, enumerations and defines
that are usefully documented elsewhere.
4. The reply error code and use of that error code when a workstation
becomes a member of a domain (to be described later). Failure to re-
turn this error code will make the workstation report that it is already
a member of the domain.
1
<mailto:linus@incolumitas.se>
Section 2.2. Notes and Structures 11
2.1.1 Sources
cket Traces from Netmonitor (Service Pack 1 and above)
ul Ashton and Luke Leighton’s other ”NT Domain” doc.
FS documentation - cifs6.txt
FS documentation - cifsrap2.txt
2.1.2 Credits
Paul Ashton: loads of work with Net Monitor; understanding the NT authentication system; reference imp
Duncan Stansfield: low-level analysis of MSRPC Pipes.
Linus Nordberg: producing c-code from Paul’s crypto spec.
Windows Sourcer development team
2.2.1 Notes
2.2.2 Enumerations
FirstFrag: 0x01
LastFrag: 0x02
NotaFrag: 0x04
RecRespond: 0x08
NoMultiplex: 0x10
Section 2.2. Notes and Structures 13
NotForIdemp: 0x20
NotforBcast: 0x40
NoUuid: 0x80
2.2.3 Structures
2.2.3.1 VOID *
2.2.3.2 char
2.2.3.3 UTIME
2.2.3.4 NTTIME
UINT32 4 - undocumented.
UINT8[] padding to get unicode string 4-byte aligned with the start of the
SMB header.
UINT32 0 - undocumented
UINT32 0 - undocumented
UINT32 5 - undocumented
Note: logon server name starts with two ’\’ characters and is upper case.
Section 2.2. Notes and Structures 17
Note: account name is the logon client name from the LSA Request Chal-
lenge, with a $ on the end of it, in upper case.
Note: logon server name starts with two ’\’ characters and is upper case.
char[8] credentials
Note: whenever this structure appears in a request, you must take a copy of
the client-calculated credentials received, because they will beused in subse-
quent credential checks. the presumed intention is to maintain an authenti-
cated request/response trail.
Note: whenever this structure appears in a request, you must take a copy of
the client-calculated credentials received, because they will be used in subse-
quent credential checks. the presumed intention is to maintain an authenti-
cated request/response trail.
UINT64 logon ID
Note: presumably, the return credentials is supposedly for the server to verify
that the credential chain hasn’t been compromised.
switch (switch_value)
case 1:
{
ID_INFO_1 id_info_1;
}
UINT32 group id
2.2.3.25 DOM INFO (domain info, levels 3 and 5 are the same))
UINT8[] ??? padding to get 4-byte alignment with start of SMB header
Note: it would be nice to know what the 16 byte user session key is for.
UINT32 User ID
UINT32 Group ID
UINT32 0 - EntriesRead
UINT32 0 - Buffer
share container with > 0 entries:
Section 2.2. Notes and Structures 25
UINT32 EntriesRead
UINT32 EntriesRead
UINT8[] padding to get unicode string 4-byte aligned with start of the
SMB header.
UINT32 EntriesRead
UINT32 0 - padding
Note: see cifs6.txt section 6.4 - the fields described therein will be of assis-
tance here. for example, the type listed below is the same as fServerType,
which is described in 6.4.1.
UINT8[] padding to get unicode string 4-byte aligned with start of the
SMB header.
with the pipe name \PIPE\srvsvc for example. You can then perform an
SMB Trans, and must carry out an SMBclose on the file handle once you
are finished.
Trans Requests must be sent with two setup UINT16s, no UINT16 params
(none known about), and UINT8 data parameters sufficient to contain the
MSRPC header, and MSRPC data. The first UINT16 setup parameter must
be either 0x0026 to indicate an RPC, or 0x0001 to indicate Set Named Pipe
Handle state. The second UINT16 parameter must be the file handle for
the pipe, obtained above.
The Data section for an API Command of 0x0026 (RPC pipe) in the Trans
Request is the RPC Header, followed by the RPC Data. The Data section
for an API Command of 0x0001 (Set Named Pipe Handle state) is two bytes.
The only value seen for these two bytes is 0x00 0x43.
MSRPC Responses are sent as response data inside standard SMB Trans
responses, with the MSRPC Header, MSRPC Data and MSRPC tail.
It is suspected that the Trans Requests will need to be at least 2-byte aligned
(probably 4-byte). This is standard practice for SMBs. It is also independent
of the observed 4-byte alignments with the start of the MSRPC header,
including the 4-byte alignment between the MSRPC header and the MSRPC
data.
To be resolved:
2.3.2 Header
2.3.2.1 RPC Packet for request, response, bind and bind acknowledge-
ment
UINT8 flags reply same as request (0x00 for Bind, 0x03 for Request)
UINT16 fraglength the length of the data section of the SMB trans
packet
UINT16 authlength
the interfaces are numbered. as yet I haven’t seen more than one interface
used on the same pipe name srvsvc
the remainder of the packet after the header if ”type” was Bind in the
response header, ”type” should be BindAck
Section 2.3. MSRPC over Transact Named Pipe 31
* abstractint USE RPC Iface num and vers. of interface client is using
* transferint USE RPC Iface num and vers. of interface to use for
replies
* port USE string the string above in single byte, null terminated form
* transfersyntax USE RPC Iface the transfer syntax from the request
the remainder of the packet after the header for every other other request
2.3.3 Tail
The end of each of the NTLSA and NETLOGON named pipes ends with:
RPC Binds are the process of associating an RPC pipe (e.g \PIPE\lsarpc)
with a ”transfer syntax” (see RPC Iface structure). The purpose for doing
this is unknown.
Note: The RPC ResBind SMB Transact request is sent with two uint16
setup parameters. The first is 0x0026; the second is the file handle returned
by the SMBopenX Transact response.
Note: The RPC ResBind members maxtsize, maxrsize and assocgid are the
same in the response as the same members in the RPC ReqBind. The
RPC ResBind member transfersyntax is the same in the response as the
34 NT Domain RPC’s Chapter 2
Note: The RPC ResBind response member secondaddr contains the name
of what is presumed to be the service behind the RPC pipe. The mapping
identified so far is:
”\\PIPE\\srvsvc” ”\\PIPE\\ntsvcs”
”\\PIPE\\samr” ”\\PIPE\\lsass”
”\\PIPE\\lsarpc” ”\\PIPE\\lsass”
”\\PIPE\\wkssvc” ”\\PIPE\\wksvcs”
”\\PIPE\\NETLOGON” ”\\PIPE\\NETLOGON”
Note: The RPC Packet fraglength member in both the Bind Request and
Bind Acknowledgment must contain the length of the entire RPC data, in-
cluding the RPC Packet header.
Request:
RPC Packet
RPC ReqBind
Response:
RPC Packet
RPC ResBind
2.3.6.1 Request
2.3.6.2 Response
Note: The info class in response must be the same as that in the request.
2.3.7.1 Request
2.3.7.2 Response
2.3.8.1 Request
no extra data
2.3.8.2 Response
2.3.9.1 Request
no extra data
2.3.9.2 Response
UINT32 0 - undocumented
UINT32 0 - undocumented
UINT32 0 - undocumented
38 NT Domain RPC’s Chapter 2
UINT32 0 - undocumented
UINT32 0 - undocumented
return 0x0C00 0034 - ”no such secret” success code
2.3.10.1 Request
2.3.10.2 Response
2.3.11.1 Request
2.3.11.2 Response
2.3.12.1 Request
2.3.12.2 Response
Note: logon server name starts with two ’\’ characters and is upper case.
Note: the initial LanManager password hash, against which the challenge
is issued, is the machine name itself (lower case). there will becalls issued
(LSA Server Password Set) which will change this, later. refusing these
calls allows you to always deal with the same password (i.e the LM# of the
machine name in lower case).
42 NT Domain RPC’s Chapter 2
2.4.1.1 Request
2.4.1.2 Response
Note: in between request and response, calculate the client credentials, and
check them against the client-calculated credentials (this process uses the
previously received client credentials).
Note: neg flags in the response is the same as that in the request.
Note: you must take a copy of the client-calculated credentials received here,
because they will be used in subsequent authentication packets.
2.4.2.1 Request
2.4.2.2 Response
Note: the new password is suspected to be a DES encryption using the old
password to generate the key.
Note: in between request and response, calculate the client credentials, and
check them against the client-calculated credentials (this process uses the
previously received client credentials).
Note: the server credentials are constructed from the client-calculated cre-
dentials and the client time + 1 second.
Note: you must take a copy of the client-calculated credentials received here,
because they will be used in subsequent authentication packets.
2.4.3.1 Request
2.4.3.2 Response
Note: valid user is True iff the username and password hash are valid for
the requested domain.
2.4.4.1 Request
2.4.4.2 Response
if (valid_user)
{
UINT16 3 - switch value indicating USER_INFO structure.
VOID* non-zero - pointer to USER_INFO structure
USER_INFO user logon information
2.4.5.1 Request
2.4.5.2 Response
2.5 \\MAILSLOT\NET\NTLOGON
Note: mailslots will contain a response mailslot, to which the response should
be sent. the target NetBIOS name is REQUEST NAME<20>, where RE-
QUEST NAME is the name of the machine that sent the request.
2.5.1.1 Request
UINT32 NTversion
UINT16 LMNTtoken
UINT16 LM20token
2.5.1.2 Response
2.5.2.1 Request
UINT32 NTversion
48 NT Domain RPC’s Chapter 2
UINT16 LMNTtoken
UINT16 LM20token
2.5.2.2 Response
UINT32 NTversion
UINT16 LMNTtoken
UINT16 LM20token
Note: share level and switch value in the response are presumably the same
as those in the request.
Note: cifsrap2.txt (section 5) may be of limited assistance here.
2.6.1.1 Request
UINT8[] padding to get unicode string 4-byte aligned with the start of the
SMB header.
2.6.1.2 Response
SHARE INFO 1 CTR share info (only added if share info ptr is non-
zero)
return 0 - indicates success
2.6.2.1 Request
2.6.2.2 Response
SERVER INFO 101 server info (only added if server info ptr is non-zero)
return 0 - indicates success
2.7.1 Definitions
ntowf() NT hash
Cc,Cs 8 byte client and server challenges Rc,Rs: 8 byte client and server
credentials
2.7.2 Protocol
C->S ReqChal,Cc
S->C Cs
C: Rc = Cred(Ks,Cc)
52 NT Domain RPC’s Chapter 2
C->S Authenticate,Rc
S: Rs = Cred(Ks,Cs), assert(Rc == Cred(Ks,Cc))
S->C Rs
C: assert(Rs == Cred(Ks,Cs))
On joining the domain the client will optionally attempt to change its pass-
word and the domain controller may refuse to update it depending on reg-
istry settings. This will also occur weekly afterwards.
2.7.3 Comments
On first joining the domain the session key could be computed by anyone
listening in on the network as the machine password has a well known value.
Until the machine is rebooted it will use this session key to encrypt NT
Section 2.8. SIDs and RIDs 53
World S-1-1-0
Local S-1-2-0
54 NT Domain RPC’s Chapter 2
NT Authority S-1-5
Dialup S-1-5-1
Network S-1-5-2
Batch S-1-5-3
Interactive S-1-5-4
Service S-1-5-6
Proxy S-1-5-8
Samba Basics
Chapter 3
SAMBA ARCHITECTURE
3.1 Introduction
People sometimes tout threads as a uniformly good thing. They are very
nice in their place but are quite inappropriate for smbd. nmbd is another
matter, and multi-threading it would be very nice.
The short version is that smbd is not multithreaded, and alternative servers
that take this approach under Unix (such as Syntax, at the time of writing)
suffer tremendous performance penalties and are less robust. nmbd is not
threaded either, but this is because it is not possible to do it while keeping
code consistent and portable across 35 or more platforms. (This drawback
also applies to threading smbd.)
57
58 Samba Architecture Chapter 3
The longer versions is that there are very good reasons for not making smbd
multi-threaded. Multi-threading would actually make Samba much slower,
less scalable, less portable and much less robust. The fact that we use a
separate process for each connection is one of Samba’s biggest advantages.
we would have to code nmbd both with and without threads, and as the
real aim of threads is to make the code clearer we would not have gained
anything. (it is a myth that threads make things faster. threading is like
recursion, it can make things clear but the same thing can always be done
faster by some other method)
Chris tried to spec out a general design that would abstract threading vs
separate processes (vs other methods?) and make them accessible through
some general API. This doesn’t work because of the data sharing require-
ments of the protocol (packets in the future depending on packets now, etc.)
At least, the code would work but would be very clumsy, and besides the
fork() type model would never work on Unix. (Is there an OS that it would
work on, for nmbd?)
A fork() is cheap, but not nearly cheap enough to do on every UDP packet
that arrives. Having a pool of processes is possible but is nasty to program
cleanly due to the enormous amount of shared data (in complex structures)
between the processes. We can’t rely on each platform having a shared
memory system.
>debughdr< :== ’[’ TIME ’,’ LEVEL ’]’ FILE ’:’ [FUNCTION] ’(’ LINE ’)’
60
Section 4.2. The DEBUG() Macro 61
Note that in the above example the function names are not listed on the
header line. That’s because the example above was generated on an SGI
Indy, and the SGI compiler doesn’t support the FUNCTION macro.
to send the output to the debug file. All of the normal printf() formatting
escapes work.
Note that in the above example the DEBUG message level is set to 0. Mes-
sages at level 0 always print. Basically, if the message level is less than or
equal to the global value DEBUGLEVEL, then the DEBUG statement is
processed.
The output of the above example would be something like:
Each call to DEBUG() creates a new header *unless* the output produced
by the previous call to DEBUG() did not end with a ’\n’. Output to the
debug file is passed through a formatting buffer which is flushed every time a
newline is encountered. If the buffer is not empty when DEBUG() is called,
the new input is simply appended.
...but that’s really just a Kludge. It was put in place because DEBUG()
has been used to write partial lines. Here’s a simple (dumb) example of the
kind of thing I’m talking about:
Without the format buffer, the output (assuming test() returned true) would
look like this:
Which isn’t much use. The format buffer kludge fixes this problem.
Produces
One of the problems with the DEBUG() macro was that DEBUG() lines
tended to get a bit long. Consider this example from nmbd sendannounce.c:
if( DEBUGLVL( 3 ) )
{
dbgtext( "send_local_master_announcement: " );
dbgtext( "type %x for name %s ", type, global_myname );
dbgtext( "on subnet %s ", subrec->subnet_name );
dbgtext( "for workgroup %s\n", work->work_group );
}
4.5.1 dbgtext()
This function prints debug message text to the debug file (and possibly
to syslog) via the format buffer. The function uses a variable argument
list just like printf() or Debug1(). The input is printed into a buffer using
Section 4.5. New Functions 65
the vslprintf() function, and then passed to format debug text(). If you
use DEBUGLVL() you will probably print the body of the message using
dbgtext().
4.5.2 dbghdr()
This is the function that writes a debug message header. Headers are not
processed via the format buffer. Also note that if the format buffer is not
empty, a call to dbghdr() will not produce any output. See the comments
in dbghdr() for more info.
It is not likely that this function will be called directly. It is used by DE-
BUG() and DEBUGADD().
This is a static function in debug.c. It stores the output text for the body
of the message in a buffer until it encounters a newline. When the newline
character is found, the buffer is written to the debug file via the Debug1()
function, and the buffer is reset. This allows us to add the indentation at
the beginning of each line of the message body, and also ensures that the
output is written a line at a time (which cleans up syslog output).
Chapter 5
SAMBA INTERNALS
In the past Samba had very ad-hoc character set handling. Scattered through-
out the code were numerous calls which converted particular strings to/from
DOS codepages. The problem is that there was no way of telling if a partic-
ular char* is in dos codepage or unix codepage. This led to a nightmare of
code that tried to cope with particular cases without handlingt the general
case.
1. all char* strings inside Samba are ”unix” strings. These are multi-byte
strings that are in the charset defined by the ”unix charset” option in
smb.conf.
2. there is no single fixed character set for unix strings, but any character
set that is used does need the following properties:
66
Section 5.2. The new functions 67
(d) must be able to correctly hold all characters that your client will
throw at it
For example, UTF-8 is fine, and most multi-byte asian character sets
are fine, but UCS2 could not be used for unix strings as they contain
nulls.
3. when you need to put a string into a buffer that will be sent on the
wire, or you need a string in a character set format that is compatible
with the clients character set then you need to use a pull or push
function. The pull functions pull a string from a wire buffer into a
(multi-byte) unix string. The push functions push a string out to a
wire buffer.
4. the two main pull and push functions you need to understand are
pull string and push string. These functions take a base pointer that
should point at the start of the SMB packet that the string is in.
The functions will check the flags field in this packet to automatically
determine if the packet is marked as a unicode packet, and they will
choose whether to use unicode for this string based on that flag. You
may also force this decision using the STR UNICODE or STR ASCII
flags. For use in smbd/ and libsmb/ there are wrapper functions clistr
and srvstr that call the pull /push functions with the appropriate
first argument.
You may also call the pull ascii/pull ucs2 or push ascii/push ucs2 func-
tions if you know that a particular string is ascii or unicode. There
are also a number of other convenience functions in charcnv.c that call
the pull /push functions with particularly common arguments, such
as pull ascii pstring()
6. all lp functions now return unix strings. The magic ”DOS” flag on
parameters is gone.
7. all vfs functions take unix strings. Don’t convert when passing to them
This section describes the macros defined in byteorder.h. These macros are
used extensively in the Samba code.
5.3.1 CVAL(buf,pos)
returns the byte at offset pos within buffer buf as an unsigned character.
5.3.2 PVAL(buf,pos)
5.3.3 SCVAL(buf,pos,val)
sets the byte at offset pos within buffer buf to value val.
5.3.4 SVAL(buf,pos)
returns the value of the unsigned short (16 bit) little-endian integer at offset
pos within buffer buf. An integer of this type is sometimes refered to as
”USHORT”.
5.3.5 IVAL(buf,pos)
returns the value of the unsigned 32 bit little-endian integer at offset pos
within buffer buf.
5.3.6 SVALS(buf,pos)
returns the value of the signed short (16 bit) little-endian integer at offset
pos within buffer buf.
Section 5.3. Macros in byteorder.h 69
5.3.7 IVALS(buf,pos)
returns the value of the signed 32 bit little-endian integer at offset pos within
buffer buf.
5.3.8 SSVAL(buf,pos,val)
sets the unsigned short (16 bit) little-endian integer at offset pos within
buffer buf to value val.
5.3.9 SIVAL(buf,pos,val)
sets the unsigned 32 bit little-endian integer at offset pos within buffer buf
to the value val.
5.3.10 SSVALS(buf,pos,val)
sets the short (16 bit) signed little-endian integer at offset pos within buffer
buf to the value val.
5.3.11 SIVALS(buf,pos,val)
sets the signed 32 bit little-endian integer at offset pos withing buffer buf to
the value val.
5.3.12 RSVAL(buf,pos)
returns the value of the unsigned short (16 bit) big-endian integer at offset
pos within buffer buf.
5.3.13 RIVAL(buf,pos)
returns the value of the unsigned 32 bit big-endian integer at offset pos
within buffer buf.
70 Samba Internals Chapter 5
5.3.14 RSSVAL(buf,pos,val)
sets the value of the unsigned short (16 bit) big-endian integer at offset pos
within buffer buf to value val. refered to as ”USHORT”.
5.3.15 RSIVAL(buf,pos,val)
sets the value of the unsigned 32 bit big-endian integer at offset pos within
buffer buf to value val.
This section describes the functions need to make a LAN Manager RPC call.
This information had been obtained by examining the Samba code and the
LAN Manager 2.0 API documentation. It should not be considered entirely
reliable.
5.4.1 Parameters
These are the parameters which you ought to send, in the order of their
appearance in the parameter block:
1. An unsigned 16 bit integer API number. You should set this value
with SSVAL(). I do not know where these numbers are described.
5. An unsigned 16 bit integer which gives the size in bytes of the buffer we
will use to receive the returned array of data structures. Presumably
this should be the same as mdrcnt. This value should be set with
SSVAL().
The code in client.c always calls call api() with no data. It is unclear when
a non-zero length data buffer would be sent.
CODING SUGGESTIONS
74
75
There are lots of platforms that Samba builds on so use caution when adding
a call to a library function that is not invoked in existing Samba code. Also
note that there are many quite different SMB/CIFS clients that Samba tries
to support, not all of which follow the SNIA CIFS Technical Reference (or
the earlier Microsoft reference documents or the X/Open book on the SMB
Standard) perfectly.
Here are some other suggestions:
1. use d printf instead of printf for display text reason: enable auto-
substitution of translated language text
2. use SAFE FREE instead of free reason: reduce traps due to null point-
ers
3. don’t use bzero use memset, or ZERO STRUCT and ZERO STRUCTP
macros reason: not POSIX
4. don’t use strcpy and strlen (use safe * equivalents) reason: to avoid
traps due to buffer overruns
5. don’t use getopt long, use popt functions instead reason: portability
6. explicitly add const qualifiers on parm passing in functions where parm
is input only (somewhat controversial but const can be #defined away)
7. when passing a va list as an arg, or assigning one to another please use
the VA COPY() macro reason: on some platforms, va list is a struct
that must be initialized in each function...can SEGV if you don’t.
8. discourage use of threads reason: portability (also see architecture.doc)
9. don’t explicitly include new header files in C files - new h files should
be included by adding them once to includes.h reason: consistency
10. don’t explicitly extern functions (they are autogenerated by ”make
proto” into proto.h) reason: consistency
11. use endian safe macros when unpacking SMBs (see byteorder.h and
internals.doc) reason: not everyone uses Intel
12. Note Unicode implications of charset handling (see internals.doc). See
pull * and push * and convert string functions. reason: Internation-
alization
13. Don’t assume English only reason: See above
76 Coding Suggestions Chapter 6
14. Try to avoid using in/out parameters (functions that return data which
overwrites input parameters) reason: Can cause stability problems
15. Ensure copyright notices are correct, don’t append Tridge’s name to
code that he didn’t write. If you did not write the code, make sure
that it can coexist with the rest of the Samba GPLed code.
16. Consider usage of DATA BLOBs for length specified byte-data. rea-
son: stability
17. Take advantage of tdbs for database like function reason: consistency
18. Don’t access the SAM ACCOUNT structure directly, they should be
accessed via pdb get...() and pdb set...() functions. reason: stability,
consistency
19. Don’t check a password directly against the passdb, always use the
check password() interface. reason: long term pluggability
20. Try to use asprintf rather than pstrings and fstrings where possible
21. Use normal C comments / * instead of C++ comments // like this.
Although the C++ comment format is part of the C99 standard, some
older vendor C compilers do not accept it.
22. Try to write documentation for API functions and structures explain-
ing the point of the code, the way it should be used, and any special
conditions or results. Mark these with a double-star comment start /
** so that they can be picked up by Doxygen, as in this file.
23. Keep the scope narrow. This means making functions/variables static
whenever possible. We don’t want our namespace polluted. Each
module should have a minimal number of externally visible functions
or variables.
24. Use function pointers to keep knowledge about particular pieces of
code isolated in one place. We don’t want a particular piece of func-
tionality to be spread out across lots of places - that makes for fragile,
hand to maintain code. Instead, design an interface and use tables
containing function pointers to implement specific functionality. This
is particularly important for command interpreters.
25. Think carefully about what it will be like for someone else to add
to and maintain your code. If it would be hard for someone else to
maintain then do it another way.
77
The suggestions above are simply that, suggestions, but the information
may help in reducing the routine rework done on new code. The preceeding
list is expected to change routinely as new support routines and macros are
added.
Chapter 7
CONTRIBUTING CODE
Here are a few tips and notes that might be useful if you are interested in
modifying samba source code and getting it into samba’s main branch.
Patch format Patches to the samba tree should be in unified diff format,
e.g. files generated by diff -u.
If you are modifying a copy of samba you retrieved from CVS, you can
easily generate a diff file of these changes by running cvs diff -u.
78
79
Feedback on your patch One of the team members will look at your
patch and either commit your patch or give comments why he won’t
apply it. In the latter case you can fix your patch and re-send it until
your patch is approved.
1
<https://bugzilla.samba.org/>
2
<mailto:samba-technical@samba.org>
Chapter 8
MODULES
8.1 Advantages
The modules system compiles a list of initialisation functions for the static
modules of each subsystem. This is a define. For example, it is here currently
80
Section 8.3. Writing modules 81
(from include/config.h):
These functions should be called before the subsystem is used. That should
be done when the subsystem is initialised or first used.
After smb probe module() has been executed, the subsystem should check
again if the module has been registered.
Each module has an initialisation function. For modules that are included
with samba this name is ’subsystem backend init’. For external modules
(that will never be built-in, but only available as a module) this name is
always ’init module’. (In the case of modules included with samba, the con-
figure system will add a #define subsystem backend init() init module()).
The prototype for these functions is:
NTSTATUS init_module(void);
This function should call one or more registration functions. The function
should return NT STATUS OK on success and NT STATUS UNSUCCESSFUL
or a more useful nt error code on failure.
NTSTATUS pdb_ldap_init(void)
{
smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam", pdb_init_ldapsam);
smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_nua", pdb_init_ldapsam_nua
return NT_STATUS_OK;
}
Some macros in configure.in generate the various defines and substs that are
necessary for the system to work correct. All modules that should be built
by default have to be added to the variable ’default modules’. For example,
if ldap is found, pdb ldap is added to this variable.
Syntax:
The depfile for a certain subsystem is the file that calls the initialisation
functions for the statically built in modules.
You must make sure all .c files that contain defines that can be changed by
./configure are rebuilded in the ’modules clean’ make target. Practically,
this means all c files that contain static init subsystem; calls need to be
rebuilded.
Section 8.3. Writing modules 83
Note
Samba Subsystems
Chapter 9
9.1 About
This document describes how to make use the new RPC Pluggable Modules
features of Samba 3.0. This architecture was added to increase the main-
tainability of Samba allowing RPC Pipes to be worked on separately from
the main CVS branch. The RPM architecture will also allow third-party
vendors to add functionality to Samba through plug-ins.
When an RPC call is sent to smbd, smbd tries to load a shared library by
the name librpc <pipename>.so to handle the call if it doesn’t know how
to handle the call internally. For instance, LSA calls are handled by librpc
lsass.so.. These shared libraries should be located in the <sambaroot>/
lib/rpc. smbd then attempts to call the init module function within the
shared library. Check the chapter on modules for more information.
In the init module function, the library should call rpc pipe register commands().
This function takes the following arguments:
version Version number of the RPC interface. Use the define SMB RPC INTERFACE VERSION
for this argument.
85
86 RPC Pluggable Modules Chapter 9
cmds a list of api structs that map RPC ordinal numbers to function calls
VFS MODULES
This abstraction layer now provides more features than a regular POSIX file
system could fill in. It is not required that all of them should be implemented
by your particular file system. However, when those features are available,
Samba would advertize them to a CIFS client and they might be used by an
application and in case of Windows client that might mean a client expects
even more additional functionality when it encounters those features. There
is a practical reason to allow handling of this snowfall without modifying the
Samba core and it is fulfilled by providing an infrastructure to dynamically
load VFS modules at run time.
Each VFS module could implement a number of VFS operations. The way
it does it is irrelevant, only two things actually matter: whether specific
implementation wants to cooperate with other modules’ implementations
or not, and whether module needs to store additional information that is
specific to a context it is operating in. Multiple VFS modules could be
loaded at the same time and it is even possible to load several instances of
the same VFS module with different parameters.
87
88 VFS Modules Chapter 10
While this structure has been first applied to the VFS subsystem, it is now
commonly used across all Samba 3 subsystems that support loadable mod-
ules. In fact, one module could provide a number of interfaces to different
subsystems by exposing different operation tables through separate initial-
ization functions.
• module name, under which Samba core will know it, and
• an operations’ table.
The operations’ table defines which functions in the module would corre-
spond to specific VFS operations and how those functions would co-operate
with the rest of VFS subsystem. Each operation could perform in a following
ways:
Section 10.1. The Samba (Posix) VFS layer 89
...
/* File operations */
90 VFS Modules Chapter 10
SMB_VFS_OP_OPEN,
SMB_VFS_OP_CLOSE,
SMB_VFS_OP_READ,
SMB_VFS_OP_WRITE,
SMB_VFS_OP_LSEEK,
SMB_VFS_OP_SENDFILE,
...
SMB_VFS_OP_LAST
} vfs_op_type;
This struct contains the function and handle pointers for all operations.
struct vfs_ops {
struct vfs_fn_pointers {
...
/* File operations */
...
} ops;
Section 10.1. The Samba (Posix) VFS layer 91
struct vfs_handles_pointers {
...
/* File operations */
...
} handles;
};
This macros SHOULD be used to call any vfs operation. DO NOT ACCESS
conn->vfs.ops.* directly !!!
...
/* File operations */
#define SMB_VFS_OPEN(conn, fname, flags, mode) \
((conn)->vfs.ops.open((conn)->vfs.handles.open,\
(conn), (fname), (flags), (mode)))
#define SMB_VFS_CLOSE(fsp, fd) \
((fsp)->conn->vfs.ops.close(\
(fsp)->conn->vfs.handles.close, (fsp), (fd)))
#define SMB_VFS_READ(fsp, fd, data, n) \
((fsp)->conn->vfs.ops.read(\
(fsp)->conn->vfs.handles.read,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_WRITE(fsp, fd, data, n) \
((fsp)->conn->vfs.ops.write(\
(fsp)->conn->vfs.handles.write,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_LSEEK(fsp, fd, offset, whence) \
((fsp)->conn->vfs.ops.lseek(\
92 VFS Modules Chapter 10
(fsp)->conn->vfs.handles.lseek,\
(fsp), (fd), (offset), (whence)))
#define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) \
((fsp)->conn->vfs.ops.sendfile(\
(fsp)->conn->vfs.handles.sendfile,\
(tofd), (fsp), (fromfd), (header), (offset), (count)))
...
These values are used by the VFS subsystem when building the conn->vfs
and conn->vfs opaque structs for a connection with multiple VFS modules.
Internally, Samba differentiates only opaque and transparent layers at this
process. Other types are used for providing better diagnosing facilities.
Most modules will provide transparent layers. Opaque layer is for modules
which implement actual file system calls (like DB-based VFS). For example,
default POSIX VFS which is built in into Samba is an opaque VFS module.
Other layer types (logger, splitter, scanner) were designed to provide differ-
ent degree of transparency and for diagnosing VFS module behaviour.
Each module can implement several layers at the same time provided that
only one layer is used per each operation.
} vfs_op_layer;
function.
name this is the name witch can be listed in the vfs objects parameter to
use this module.
void* op;
vfs_op_type type;
vfs_op_layer layer;
} vfs_op_tuple;
type the vfs op type of the function to specified witch operation the func-
tion provides.
NTSTATUS init_module(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "example", example_op_tuple
}
Each VFS function has as first parameter a pointer to the modules vfs handle struct.
param this is the module parameter specified in the vfs objects parame-
ter.
e.g. for ’vfs objects = example:test’ param would be ”test”.
vfs next This vfs ops struct contains the information for calling the next
module operations. Use the SMB VFS NEXT * macros to call a next
module operations and don’t access handle->vfs next.ops.* directly!
conn This is a pointer back to the connection struct to witch the handle
belongs.
data This is a pointer for holding module private data. You can alloc
data with connection life time on the handle->conn->mem ctx TAL-
LOC CTX. But you can also manage the memory allocation yourself.
free data This is a function pointer to a function that free’s the module
private data. If you talloc your private data on the TALLOC CTX
handle->conn->mem ctx, you can set this function pointer to NULL.
Some useful MACROS for handle private data.
if (!(handle)) { \
DEBUG(0,("%s() failed to set handle->data!\n",FUNCTION_MACRO)); \
ret; \
} else { \
if ((handle)->free_data) { \
(handle)->free_data(&(handle)->data); \
} \
(handle)->data = (void *)datap; \
(handle)->free_data = free_fn; \
} \
}
#define SMB_VFS_HANDLE_FREE_DATA(handle) { \
if ((handle) && (handle)->free_data) { \
(handle)->free_data(&(handle)->data); \
} \
}
How SMB VFS LAYER TRANSPARENT functions can call the SMB VFS LAYER OPAQUE
functions.
The easiest way to do this is to use the SMB VFS OPAQUE * macros.
...
/* File operations */
#define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) \
((conn)->vfs_opaque.ops.open(\
(conn)->vfs_opaque.handles.open,\
(conn), (fname), (flags), (mode)))
#define SMB_VFS_OPAQUE_CLOSE(fsp, fd) \
((fsp)->conn->vfs_opaque.ops.close(\
(fsp)->conn->vfs_opaque.handles.close,\
(fsp), (fd)))
#define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) \
((fsp)->conn->vfs_opaque.ops.read(\
(fsp)->conn->vfs_opaque.handles.read,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_OPAQUE_WRITE(fsp, fd, data, n) \
((fsp)->conn->vfs_opaque.ops.write(\
Section 10.2. The Interaction between the Samba VFS subsystem and the modules 97
(fsp)->conn->vfs_opaque.handles.write,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) \
((fsp)->conn->vfs_opaque.ops.lseek(\
(fsp)->conn->vfs_opaque.handles.lseek,\
(fsp), (fd), (offset), (whence)))
#define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) \
((fsp)->conn->vfs_opaque.ops.sendfile(\
(fsp)->conn->vfs_opaque.handles.sendfile,\
(tofd), (fsp), (fromfd), (header), (offset), (count)))
...
How SMB VFS LAYER TRANSPARENT functions can call the next mod-
ules functions.
The easiest way to do this is to use the SMB VFS NEXT * macros.
...
/* File operations */
#define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) \
((handle)->vfs_next.ops.open(\
(handle)->vfs_next.handles.open,\
(conn), (fname), (flags), (mode)))
#define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) \
((handle)->vfs_next.ops.close(\
(handle)->vfs_next.handles.close,\
(fsp), (fd)))
#define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) \
((handle)->vfs_next.ops.read(\
(handle)->vfs_next.handles.read,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n) \
((handle)->vfs_next.ops.write(\
(handle)->vfs_next.handles.write,\
(fsp), (fd), (data), (n)))
#define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) \
((handle)->vfs_next.ops.lseek(\
(handle)->vfs_next.handles.lseek,\
(fsp), (fd), (offset), (whence)))
98 VFS Modules Chapter 10
1. Add ”vfs handle struct *handle, ” as first parameter to all vfs oper-
ation functions. e.g. example connect(connection struct *conn, const
char *service, const char *user); -> example connect(vfs handle struct
*handle, connection struct *conn, const char *service, const char *user);
2. Replace ”default vfs ops.” with ”smb vfs next ”. e.g. default vfs ops.connect(conn,
service, user); -> smb vfs next connect(conn, service, user);
3. Uppercase all ”smb vfs next *” functions. e.g. smb vfs next connect(conn,
service, user); -> SMB VFS NEXT CONNECT(conn, service, user);
4. Add ”handle, ” as first parameter to all SMB VFS NEXT *() calls.
e.g. SMB VFS NEXT CONNECT(conn, service, user); -> SMB VFS NEXT CONNECT(h
conn, service, user);
5. (Only for 2.2.* modules) Convert the old struct vfs ops example ops
to a vfs op tuple example op tuples[] array. e.g.
/* File operations */
NULL, /* open */
NULL, /* close */
NULL, /* read */
NULL, /* write */
NULL, /* lseek */
NULL, /* sendfile */
NULL, /* rename */
NULL, /* fsync */
example_stat, /* stat */
example_fstat, /* fstat */
example_lstat, /* lstat */
NULL, /* unlink */
NULL, /* chmod */
NULL, /* fchmod */
NULL, /* chown */
NULL, /* fchown */
NULL, /* chdir */
NULL, /* getwd */
NULL, /* utime */
NULL, /* ftruncate */
NULL, /* lock */
NULL, /* symlink */
NULL, /* readlink */
NULL, /* link */
NULL, /* mknod */
NULL, /* realpath */
NULL, /* fget_nt_acl */
NULL, /* get_nt_acl */
NULL, /* fset_nt_acl */
NULL, /* set_nt_acl */
NULL, /* chmod_acl */
NULL, /* fchmod_acl */
NULL, /* sys_acl_get_entry */
NULL, /* sys_acl_get_tag_type */
NULL, /* sys_acl_get_permset */
NULL, /* sys_acl_get_qualifier */
NULL, /* sys_acl_get_file */
100 VFS Modules Chapter 10
NULL, /* sys_acl_get_fd */
NULL, /* sys_acl_clear_perms */
NULL, /* sys_acl_add_perm */
NULL, /* sys_acl_to_text */
NULL, /* sys_acl_init */
NULL, /* sys_acl_create_entry */
NULL, /* sys_acl_set_tag_type */
NULL, /* sys_acl_set_qualifier */
NULL, /* sys_acl_set_permset */
NULL, /* sys_acl_valid */
NULL, /* sys_acl_set_file */
NULL, /* sys_acl_set_fd */
NULL, /* sys_acl_delete_def_file */
NULL, /* sys_acl_get_perm */
NULL, /* sys_acl_free_text */
NULL, /* sys_acl_free_acl */
NULL /* sys_acl_free_qualifier */
};
->
NTSTATUS init_module(void)
{
Section 10.3. Upgrading to the New VFS Interface 101
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,"example",example_op_tuples);
}
8. Check if your vfs init() function does more then just prepare the
If NOT you can remove the vfs init() fu
vfs ops structs or remember the struct smb vfs handle struct.
If YES decide if you want to move the
9. (Only for 3.0alpha* modules) Check if your vfs done() function con-
If NOT you can remove the vfs done() function.
tains needed code.
If YES decide if you can move the code to the example disconnect() operation. O
10. Check if you have any global variables left. Decide if it wouldn’t be bet-
If NOT leave them as they are. (e.g. this could be the var
ter to have this data on a connection basis.
If YES pack all this data into a struct. You can use handl
e.g. if you have such a struct:
struct example_privates {
char *some_string;
int db_connection;
};
DEBUG(0,("talloc_strdup() failed\n"));
return -1;
}
data->db_connection = open_db_conn();
return SMB_VFS_NEXT_CONNECT(handle,conn,service,user);
}
/* do something here...*/
DEBUG(0,("some_string: %s\n",data->some_string));
SAFE_FREE(data->some_string);
SAFE_FREE(data);
Section 10.3. Upgrading to the New VFS Interface 103
*datap = NULL;
return;
}
data->db_connection = open_db_conn();
return SMB_VFS_NEXT_CONNECT(handle,conn,service,user);
}
/* do something here...*/
DEBUG(0,("some_string: %s\n",data->some_string));
The idea is that you can extend this configure.in and Makefile.in
scripts for your module.
./configure --enable-developer ...
make
12. Compiling & Testing... Try to fix all compiler warnings
make
Testing, Testing, Testing ...
Basically, the file is processed on a line by line basis. There are four types
of lines that are recognized by the lexical analyzer (params.c):
The first two are handled exclusively by the lexical analyzer, which ignores
them. The latter two line types are scanned for
1. - Section names
2. - Parameter names
3. - Parameter values
These are the only tokens passed to the parameter loader (loadparm.c).
Parameter names and values are divided from one another by an equal sign:
’=’.
106
Section 11.1. Lexical Analysis 107
1. The lexical analyzer scans past white space at the beginning of a line.
2. Section and parameter names may contain internal white space. All
whitespace within a name is compressed to a single space character.
Long section header and parameter lines may be extended across multiple
lines by use of the backslash character (’\\’). Line continuation is ignored
for blank and comment lines.
Would be read as
Note that there are five spaces following the word ’string’, representing the
one space between ’string’ and ’\\’ in the top line, plus the four preceeding
the word ’with’ in the second line. (Yes, I’m counting the indentation.)
Line continuation characters are ignored on blank lines and at the end of
comments. They are *only* recognized within section and parameter lines.
108 The smb.conf file Chapter 11
The middle line is *not* parsed as a blank line because it is first concatonated
with the top line. The result is
This becomes:
are read as
[section name]
param name = value
Section 11.2. Syntax 109
11.2 Syntax
The parsing of the config file is a bit unusual if you are used to lex, yacc,
bison, etc. Both lexical analysis (scanning) and parsing are performed by
params.c. Values are loaded via callbacks to loadparm.c.
Chapter 12
The current Samba codebase possesses the capability to use groups of WINS
servers that share a common namespace for NetBIOS name registration and
resolution. The formal parameter syntax is
[global]
wins server = 192.168.1.2 192.168.1.3
In the event that no TAG is defined in for a SERVER in the list, smbd
assigns a default TAG of ”*”. A TAG is used to group servers of a shared
NetBIOS namespace together. Upon startup, nmbd will attempt to register
the netbios name value with one server in each tagged group.
An example using tags to group WINS servers together is show here. Note
that the use of interface names in the tags is only by convention and is not
110
Section 12.1. WINS Failover 111
a technical requirement.
[global]
wins server = 192.168.1.2:eth0 192.168.1.3:eth0 192.168.2.2:eth1
Using this configuration, nmbd would attempt to register the server’s Net-
BIOS name with one WINS server in each group. Because the ”eth0” group
has two servers, the second server would only be used when a registration
(or resolution) request to the first server in that group timed out.
NetBIOS name resolution follows a similar pattern as name registration.
When resolving a NetBIOS name via WINS, smbd and other Samba pro-
grams will attempt to query a single WINS server in a tagged group until
either a positive response is obtained at least once or until a server from ev-
ery tagged group has responded negatively to the name query request. If a
timeout occurs when querying a specific WINS server, that server is marked
as down to prevent further timeouts and the next server in the WINS group
is contacted. Once marked as dead, Samba will not attempt to contact that
server for name registration/resolution queries for a period of 10 minutes.
Chapter 13
LANMAN AND NT
PASSWORD ENCRYPTION
13.1 Introduction
This document describes how the SMB password encryption algorithm works
and what issues there are in choosing whether you want to use it. You
should read it carefully, especially the part about security and the ”PROS
and CONS” section.
112
Section 13.3. The smbpasswd file 113
to retrieve the cleartext of the user’s password given the UNIX hash of it),
a separate password file containing this 16 byte value must be kept. To
minimise problems with these two password files, getting out of sync, the
UNIX /etc/passwd and the smbpasswd file, a utility, mksmbpasswd.sh,
is provided to generate a smbpasswd file from a UNIX /etc/passwd file.
To generate the smbpasswd file from your /etc/passwd file use the following
command:
$cat /etc/passwd | mksmbpasswd.sh > /usr/local/samba/private/smbpasswd
If you are running on a system that uses NIS, use
$ypcat passwd | mksmbpasswd.sh > /usr/local/samba/private/smbpasswd
The mksmbpasswd.sh program is found in the Samba source directory.
By default, the smbpasswd file is stored in :
/usr/local/samba/private/smbpasswd
The owner of the /usr/local/samba/private/ directory should be set to
root, and the permissions on it should be set to 0500 (chmod 500 /us-
r/local/samba/private).
Likewise, the smbpasswd file inside the private directory should be owned
by root and the permissions on is should be set to 0600 (chmod 600 smb-
passwd).
The format of the smbpasswd file is (The line has been wrapped here. It
should appear as one entry per line in your smbpasswd file.)
username:uid:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:
[Account type]:LCT-<last-change-time>:Long name
When the password file is created all users have password entries consisting
of 32 ’X’ characters. By default this disallows any access as this user. When
a user has a password set, the ’X’ characters change to 32 ascii hexadecimal
digits (0-9, A-F). These are an ascii representation of the 16 byte hashed
value of a user’s password.
To set a user to have no password (not recommended), edit the file using
vi, and replace the first 11 characters with the ascii text "NO PASSWORD"
(minus the quotes).
For example, to clear the password for user bob, his smbpasswd file entry
would look like :
bob:100:NO PASSWORDXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:
[U ]:LCT-00000000:Bob’s full name:/bobhome:/bobshell
If you are allowing users to use the smbpasswd command to set their own
passwords, you may want to give users NO PASSWORD initially so they do
not have to enter a previous password when changing to their new password
(not recommended). In order for you to allow this the smbpasswd program
must be able to connect to the smbd daemon as that user with no password.
Enable this by adding the line :
null passwords = yes
to the [global] section of the smb.conf file (this is why the above scenario
is not recommended). Preferably, allocate your users a default password to
begin with, so you do not have to enable this on your server.
Note :This file should be protected very carefully. Anyone with access to
this file can (with enough knowledge of the protocols) gain access to your
SMB server. The file is thus more sensitive than a normal unix /etc/passwd
file.
Part IV
This file describes how to do a system call trace on Samba to work out what
its doing wrong. This is not for the faint of heart, but if you are reading
this then you are probably desperate.
Actually its not as bad as the the above makes it sound, just don’t expect
the output to be very pretty :-)
Ok, down to business. One of the big advantages of unix systems is that they
nearly all come with a system trace utility that allows you to monitor all
system calls that a program is making. This is extremely using for debugging
and also helps when trying to work out why something is slower than you
expect. You can use system tracing without any special compilation options.
The system trace utility is called different things on different systems. On
Linux systems its called strace. Under SunOS 4 its called trace. Under
SVR4 style systems (including solaris) its called truss. Under many BSD
systems its called ktrace.
The first thing you should do is read the man page for your native system
call tracer. In the discussion below I’ll assume its called strace as strace is
the only portable system tracer (its available for free for many unix types)
and its also got some of the nicest features.
Next, try using strace on some simple commands. For example, strace ls
or strace echo hello.
You’ll notice that it produces a LOT of output. It is showing you the
arguments to every system call that the program makes and the result.
117
118 Tracing samba system calls Chapter 14
Very little happens in a program without a system call so you get lots of
output. You’ll also find that it produces a lot of ”preamble” stuff showing
the loading of shared libraries etc. Ignore this (unless its going wrong!)
For example, the only line that really matters in the strace echo hello
output is:
write(1, "hello\n", 6) = 6
SAMBA PRINTING
INTERNALS
15.1 Abstract
The purpose of this document is to provide some insight into Samba’s print-
ing functionality and also to describe the semantics of certain features of
Windows client printing.
120
Section 15.3. Print Queue TDB’s 121
Samba provides periodic caching of the output from the ”lpq command” for
performance reasons. This cache time is configurable in seconds. Obviously
the longer the cache time the less often smbd will be required to exec a
copy of lpq. However, the accuracy of the print queue contents displayed to
clients will be diminished as well.
The list of currently opened print queue TDB’s can be found be examin-
ing the list of tdb print db structures ( see print db head in printing.c ). A
queue TDB is opened using the wrapper function printing.c:get print db byname().
The function ensures that smbd does not open more than MAX PRINT DBS OPEN
in an effort to prevent a large print server from exhausting all available file
descriptors. If the number of open queue TDB’s exceeds the MAX PRINT DBS OPEN
limit, smbd falls back to a most recently used algorithm for maintaining a
list of open TDB’s.
There are two ways in which a a print job can be entered into a print queue’s
TDB. The first is to submit the job from a Windows client which will insert
the job information directly into the TDB. The second method is to have
the print job picked up by executing the ”lpq command”.
The current manifestation of the printjob structure contains a field for the
UNIX job id returned from the ”lpq command” and a Windows job ID (32-
bit bounded by PRINT MAX JOBID). When a print job is returned by the
”lpq command” that does not match an existing job in the queue’s TDB, a
32-bit job ID above the <*vance doesn’t know what word is missing here*>
is generating by adding UNIX JOB START to the id reported by lpq.
In order to match a 32-bit Windows jobid onto a 16-bit lanman print job id,
smbd uses an in memory TDB to match the former to a number appropriate
for old lanman clients.
When updating a print queue, smbd will perform the following steps ( refer
to print.c:print queue update() ):
2. Lock the mutex entry in the TDB and store our own pid. Check that
this succeeded, else fail.
3. Store the updated time stamp for the new cache listing
5.
foreach job in the queue
{
if the job is a UNIX job, create a new entry;
if the job has a Windows based jobid, then
{
Lookup the record by the jobid;
if the lookup failed, then
treat it as a UNIX job;
else
update the job status only
}
}
Section 15.4. ChangeID and Client Caching of Printer Information 123
6. Delete any jobs in the TDB that are not in the in the lpq listing
7. Store the print queue status in the TDB
8. update the cache time stamp again
Note that it is the contents of this TDB that is returned to Windows clients
and not the actual listing from the ”lpq command”.
The NT DEVICEMODE stored as part of the printjob structure is used
to store a pointer to a non-default DeviceMode associated with the print
job. The pointer will be non-null when the client included a Device Mode
in the OpenPrinterEx() call and subsequently submitted a job for printing
on that same handle. If the client did not include a Device Mode in the
OpenPrinterEx() request, the nt devmode field is NULL and the job has
the printer’s device mode associated with it by default.
Only non-default Device Mode are stored with print jobs in the print queue
TDB. Otherwise, the Device Mode is obtained from the printer object when
the client issues a GetJob(level == 2) request.
When working with Windows NT+ clients, it is possible for a print server
to use RPC to send asynchronous change notification events to clients for
certain printer and print job attributes. This can be useful when the client
needs to know that a new job has been added to the queue for a given printer
or that the driver for a printer has been changed. Note that this is done
entirely orthogonal to cache updates based on a new ChangeID for a printer
object.
The basic set of RPC’s used to implement change notification are
• RemoteFindFirstPrinterChangeNotifyEx ( RFFPCN )
• RemoteFindNextPrinterChangeNotifyEx ( RFNPCN )
• FindClosePrinterChangeNotify( FCPCN )
124 Samba Printing Internals Chapter 15
• ReplyOpenPrinter
• ReplyClosePrinter
• RouteRefreshPrinterChangeNotify ( RRPCN )
One additional RPC is available to a server, but is never used by the Win-
dows spooler service:
• RouteReplyPrinter()
The opnum for all of these RPC’s are defined in include/rpc spoolss.h
Windows NT print servers use a bizarre method of sending print notification
event to clients. The process of registering a new change notification handle
is as follows. The ’C’ is for client and the ’S’ is for server. All error conditions
have been eliminated.
• The count field is the number of entries in the SPOOL NOTIFY INFO DATA
array
The SPOOL NOTIFY INFO DATA entries contain:
• The type defines whether or not this event is for a printer or a print
job
• The field is the flag identifying the event
• the notify data union contains the new valuie of the attribute
• The enc type defines the size of the structure for marshalling and un-
marshalling
• (a) the id must be 0 for a printer event on a printer handle. (b) the
id must be the job id for an event on a printer job (c) the id must be
the matching number of the printer index used in the response packet
to the RFNPCN when using a print server handle for notification.
Samba currently uses the snum of the printer for this which can break
if the list of services has been modified since the notification handle
was registered.
• The size is either (a) the string length in UNICODE for strings, (b)
the size in bytes of the security descriptor, or (c) 0 for data values.
Part V
Appendices
Chapter 16
NOTES TO PACKAGERS
16.1 Versioning
16.2 Modules
Samba3 has support for building parts of samba as plugins. This makes it
possible to, for example, put ldap or mysql support in a separate package,
thus making it possible to have a normal samba package not depending on
ldap or mysql. To build as much parts of samba as a plugin, run:
The option --with-shared-modules is maintained to support specific mod-
ules such as idmap XXX and vfs XXX. For example, --with-shared-modules=idmap
ad. Use of this parameter to the configure command as not been supported
in official releases.
./configure --with-shared-modules=rpc,vfs,auth,pdb,charset
127