Introduction to Samba

Introduction

Samba is an open-source implementation of the SMB/CIFS protocol that Microsoft uses to connect hosts to share drives and printers.

The Big picture

If you want to log who does what on the Samba server, each Windows user must have their own Linux account. To share a directory or printer on a Linux server with Windows users, you must first create accounts on the Linux host (No need to provide a login shell if the user will only interact with the server through Samba), then use smbpasswd (or pdbedit) to add their password to the Samba password database (since password hashing in Linux and Windows aren't compatible), edit smb.conf to share a directory, and finally check Unix file access rights on that directory to make sure Samba and Windows users can work with it as planned. Samba can further restrict access rights, but cannot add more than those set by Unix.

Generally speaking, remember that Samba is just a layer on top of Unix: This means that things must be configured right both in Samba and Unix (user accounts, file access rights).

Things to know:

  1. Make sure both hosts are reachable over the network (ping), and firewalls are configured to handle NetBIOS packets
  2. To share a directory in read-only, you just need to make sure /etc/passwd includes "nobody", the target shared directory exists and belongs to "nobody" (chown -R nobody:nogroup /my/share; chmod 770 /my/share)
  3. After editing smb.conf, always run "testparm smb.conf". Note that this will leave out default settings; For a full dump, run "testparm -sv smb.conf". You can also use testparm to check access from a remote host: testparm /etc/samba/smb.conf remote-laptop 10.0.0.1
  4. Once Samba is up and running, you can open a DOS box on the remote Windows host, and type "net view \\192.168.0.1" to list the shares on that host, and "net view" to view all available hosts on the network; If "net view" doesn't work, there's a problem with network browsing
  5. Remember to run eg. "/etc/init.d/samba reload" or sometimes "/etc/init.d/samba restart" after editing smb.conf; Check /var/log/messages and /var/log/samba/ for more information

As of 2023, the only books available were published long ago; The wiki is today's authoritive source of infos:

https://wiki.samba.org/index.php/User_Documentation
https://wiki.samba.org/index.php/Setting_up_Samba_as_a_Standalone_Server
https://wiki.samba.org/index.php/FAQ#Samba_as_an_standalone_server

Since NetBIOS is definitely on its way out since SMBv1 had to be turned off after WannaCry, take a look at wsdd/Avahi/Bonjour (so Samba hosts can advertise themselves on the network) and DynamicDNS (what Linux implementation?)

Installing Samba on Debian

Ubuntu (11.04) offers several packages to install Samba. Note that "samba" refers implicitely to Samba 3, while samba4 refers to... Samba 4.

Here are the Samba 3 packages:

Here's to install Samba:

  1. apt-get update
  2. apt-get install samba samba-common
  3. To check that Samba is running: ps aux ; netstat -tunlp
  4. To restart the two services:
    systemctl restart smbd.service
    systemctl restart nmbd.service
  5. To check that smb.conf is correct: testparm
  6. Log files in /var/log/samba/
  7. To check if *nmd services launch at boot time: systemctl list-unit-files --type=service | grep mbd

Installing Samba on Fedora 5

http://www.reallylinux.com/docs/sambaserver.shtml

http://www.reallylinux.com/docs/windowstolinux.shtml

[root@sip asterisk]# yum search samba

Securing Samba

Network Browsing

LATER

NetBIOS UDP

WINS, /etc/hosts, DNS

Domain master browser

Local master browser

wsdd

With SMB1 gone because of WannaCry, wsdd lets a Samba server show up in Windows' Network Neighborhood.

apt-get install wsdd

If unavailable as a package:

wget -O- https://pkg.ltec.ch/public/conf/ltec-ag.gpg.key | gpg --dearmour > /usr/share/keyrings/wsdd.gpg
 
source /etc/os-release
 
;IMPORTANT: All on a single line!
echo "deb [signed-by=/usr/share/keyrings/wsdd.gpg] https://pkg.ltec.ch/public/ ${UBUNTU_CODENAME:-${VERSION_CODENAME:-UNKNOWN}} main" > /etc/apt/sources.list.d/wsdd.list
 
apt update
 
apt-get install wsdd

service wsdd start

Python script listening on TCP5357 and and UDP3702/46744.

Infos:

smb.conf Samples

Anonymous Read-Only Document Server

Here's /etc/samba/smb.conf:

[global]
workgroup = WORKGROUP
;netbios name = LINUX
 
;Note: security = share is deprecated
security = user
map to guest = bad user
 
;required to make this host master browser and WINS server
wins support = yes
local master = yes
preferred master = yes
domain master = yes
os level = 255
 
;to solve the "WINS server 127.0.0.1 timed out registering IP" message
interfaces = eth0 lo
bind interfaces only = yes
 
;this avoids needless errors in the logs if you have no printer
printcap name = /dev/null
load printers = no
printing = bsd
 
[myshare]
comment = Some comment
path = /my/share
;users will share the "nobody" Unix account
guest ok = yes 
read only = yes
browseable = yes

Here's a newer version, for Samba4 and without WINS (since it's gone with SMB1 turned off):

[global]
workgroup = WORKGROUP
netbios name = MYSRV
server string = Some great server
server role = standalone server
;guest account = nobody
guest account = www-data
map to guest = Bad User
hosts allow = 127.0.0.1 192.168.0.0/24
hosts deny = 0.0.0.0/0
interfaces = lo enp0s20
bind interfaces only = yes
disable netbios = yes
 
log file = /var/log/samba/%m
log level = 1
 
; printers are disabled
disable spoolss = Yes
load printers = No
printcap name = /dev/null
printing = bsd
show add printer wizard= No
 
[guest]
# This share allows anonymous (guest) access without authentication!
path = /var/www/html/
;read only = no
writeable = yes
guest ok = yes
guest only = yes
browseable = yes
comment = Some great directory
public = yes
force create mode = 0660
;force directory mode = 2770
force directory mode = 0770

Anonymous Read-Write Document Server

To let 1) Windows users who log onto their computer without a password 2) connect to a Samba share without typing a password either, here's the smb.conf you can use. This is a very insecure solution since all users will connect and work with the Unix account "nobody", but it can be appropriate for a home solution:

[global]
workgroup = WORKGROUP
netbios name = LINUX
 
;a bit of security
hosts allow = 127.0.0.1 192.168.0.0/24
hosts deny = 0.0.0.0/0
interfaces = eth0 lo
bind interfaces only = yes
 
;security = share is deprecated
security = user
 
;So users don't get 'System error 5 has occurred. Access is denied." when running "net view \\linux"
map to guest = bad user
 
;by default, guest account defaults to Unix user "nobody". Can be changed with "guest account"
;but make sure some.account.other.than.nobody has read-write access to the shared directory
;guest account = some.account.other.than.nobody
 
;interfaces = lo eth0
;if nmbd fails starting, make sure "interfaces" is set to the right interface name
interfaces = 192.168.0.15/255.255.255.0 127.0.0.1/255.255.255.255
 
;to solve the "WINS server 127.0.0.1 timed out registering IP" message
bind interfaces only = yes
 
wins support = no
;to make the host the WINS server
;wins support = yes
;local master = yes
;preferred master = yes
;domain master = yes
;os level = 255
 
;this avoids needless errors in the logs if you have no printer
printcap name = /dev/null
load printers = no
printing = bsd
 
[myshare]
comment = Data
path = /myshare
;Remember to run "chown -R guest.account /myshare"
writable = yes
guest ok = yes
 
browseable=yes
force create mode = 0644
create mask = 0664
#Unknown parameter encountered: "security mask"
security mask = 0664
#Unknown parameter encountered: "force security mode"
force security mode = 0664

Secure Read-Write File and Print Server

This requires first adding a user + password in /etc/passwd and a matching account in the Samba database (smbpass -a jdoe); This user account + password must match the one in Windows so that the user isn't prompted when trying to connect to a Samba share:

mkdir /export
;Assume all Samba users belong to "nogroup"
chown nobody:nogroup /export
chmod 770 /export

Here's smb.conf:

[global]
workgroup = WORKGROUP
netbios name = LINUX
 
[homes]
comment = Home Directories
valid users = %S
read only = No
browseable = No
 
[public]
comment = Data
path = /export
read only = No

Changing a user's encrypted password on an NT PDC

As root, run smbpasswd -r MYPDC. To specify a user account different from root, use the -U option

security=share or security=user

When using Samba with those options, you need to create user accounts on the Samba server. If user accounts have already been created on a Windows NT Primary Domain Controller, this means keeping a second user database... and updating passwords whenever users change their password on the PDC :-( To avoid this, use security=(server | domain)

security=server or security=domain

This options tells Samba to query NT DCs to authenticate users, ie. you do not need to set passwords on the Samba server. You do need, however, to create user accounts to match the ones that live on the DC, unless you prefer to use a common account through the force user = jdoe option (not recommended.)

The Samba documentation mentions a add_user script that lets Samba create user accounts on the fly when a new NT user connects to Samba, but I haven't found a trace of it in the 2.0.7-x RPM package that I installed.

I haven't tried it yet, but the following could work: add user script = /usr/sbin/useradd %u. With security=( server | domain), Samba does not store a copy of user passwords; it forwards the authentication step to a DC. So, I guess you can leave those dynamicall-created accounts with no password, and not worry about running passwd or smbpasswd.

To authenticate users against NT DCs, set password server = MYPDC, MYBDC. Alternatively, set password server = * to tell Samba to find DCs itself (by querying a WINS server or other means, and look for MYDOMAIN<1C> resources.)

Securing Samba through IPs

Here's how to configure Samba so it will only accept connections from certain IPs:

hosts allow = 127.0.0.1 192.168.2.0/24 192.168.3.0/24

hosts deny = 0.0.0.0/0

Making Samba a member of an NT domain

The goal is to create a computer account to make the Samba server a member of an NT domain, just like any other NT host:
  1. Stop Samba
  2. On the NT PDC, create a computer account for the Samba server
  3. On the Samba server, edit /etc/smb.conf, set security=domain and password server = MYPDC MYBDC. If MYPDC cannot be resolved, check that NetBIOS name resolving works.
  4. run smbpasswd -J MYDOMAIN
Note that you can also indicate the name of the PDC through eg. smbpassd -J MYDOMIN -R MYPDC. You MUST its NetBIOS name, not its IP address. Once the Samba server has joind the NT domain, its computer password is saved in a file called ..mac .

Samba as PDC for NT clients

Samba 2.0.x can act as PDC only to NT4 clients. If  you have Windows2000 clients, you'll have to use Samba 2.2.x or the forked branch Samba TNG ("The New Generation.") As of June 2001, I have only tested the 2.2.x version, which seems to work.

Setup

  1. Install Samba 2.2.x
  2. Create an empty smbpasswd file: touch /etc/samba/smbpasswd ; chmod go-rwx /etc/samba/smbpasswd
  3. Create a group to contain computer accounts: grpadd machines
  4. Create an administrator account that is allowed to add hosts to the domain: useradd -c "Samba admin account" -s /bin/false -d /dev/null ntadmin ; smbpasswd -a ntadmin
  5. Create a computer account for the new W2K host you wish to add to the domain: useradd -g machines -c "W2K host" -s /bin/false -d /dev/null w2kclient$ ; smbpasswd -a -m w2kclient$
  6. Create a user account for the W2K user: useradd -c "User account" -s /bin/bash -d /home/jdoe jdoe ; smbpasswd -a jdoe
  7. Edit smb.conf:
    workgroup = MYDOMAIN
  8. security = user
    encrypt passwords = yes
    #Just to make sure this host wins any election to become master browser
    os level = 255
    local master = yes
    domain master = yes
    preferred master = yes
    domain logons = yes

    ;   logon script = %m.bat
    # run a specific logon batch file per username
    ;   logon script = %U.bat
     
    # Where to store roving profiles (only for Win95 and WinNT)
    #        %L substitutes for this servers netbios name, %U is username
    #        You must uncomment the [Profiles] share below
    #   logon path = \\%L\Profiles\%U
    #logon drive = H:
    #logon home = \\%N\%U\profile
    wins support = yes

    [netlogon]
    comment = Network Logon Service
    write list = ntadmin
    path = /var/log/samba/netlogon
    ;   guest ok = yes
    writable = no
    ;   share modes = no
     
    # Un-comment the following to provide a specific roving profile share
    # the default is to use the user's home directory
    [Profiles]
    path = /var/log/samba/ntprofile
    writable = yes
    create mask = 0600
    directory mask = 0700
    ;    browseable = no
    ;    guest ok = yes
  9. On the W2K client, right-click on My Computer, followed by Properties | Network Identification | Properties, and select Domain. Use the ntadmin account defined above to add this host to the domain. There is a 60s wait until you get the "Welcome to xxx domain" dialog. Reboot.
  10. Log on with the user account that you defined above (jdoe, here)

Winbind: Delegating Unix authentication to an NT PDC

Haven't tried yet. http://www.ibiblio.org/pub/packages/samba/docs/htmldocs/winbind.html

Sharing a Linux printer through Samba

[global]
        printing = BSD
        print command = /usr/bin/lpr -r  %s
	printcap file = /etc/printcap

[printers]
        path = /var/spool/printer
        printable = true 
        guest ok = true
        guest account = pcguest

[printer1]
        printable = yes
        printer = lp
        read only = yes
        guest ok = yes
If you create a share named [printers] in the configuration file, Samba will automatically read in your printer capabilities file and create a printing share for each printer that appears in the file. Second, try the command testprns printername. This is a simple program that verifies that the specified printer is available in your printcap file. If your printcap file is not in the usual place, you can specify its full pathname as the second argument to the testprns command: # testprns lp /etc/printcap Looking for printer lp in printcap file /etc/printcap Printer name lp is valid. Just like NT, Samba can send the ad hoc printer driver the first time a user installs the printer on his Windows client. This is to avoid having each user run the Printer Wizard on his Windows client:
  1. Install the drivers for the printer on a Windows client (the printer need not be attached).
  2. Create a printer definition file from the information on a Windows machine: Go into c:\windows\inf\, and grep through MSPRINT?.INF to find the record for the driver. Once you found which MSPRINT?.INF contains the right driver, make_printerdef MSPRINT3.INF "HP DeskJet 560C Printer" >printers.def.
  3. Create a PRINTER$ share where the resulting driver files can be placed, as indicated by make_printerdef. Remember to also copy printers.def into the directory pointed to by PRINTER$ [PRINTER$] path = /usr/local/samba/print read only = yes browsable = no guest ok = yes
  4. Modify the Samba configuration file accordingly. [global] printer driver file = /usr/local/samba/print/printers.def [hpdeskjet] path = /var/spool/samba/printers printable = yes printer driver = HP DeskJet 560C Printer printer driver location = \\%L\PRINTER$

Disabling use of encrypted password mode in 9x/NT

By default, 95-OSR2, 98, NT4 SP3, and W2K hosts send the user's password encrypted, which is a good thing since it makes it more difficult for hackers to collect passwords by listening to traffic on your network.

The best solution is to set up the Samba server to handle encrypted passwords by adding "encrypt password=yes" in smb.conf, and managing encrypted passwords, either by converting hashed passwords from /etc/shadow into /etc/smbpasswd when using security=[ share | user ] (which is a better solution than having users set their Unix password into /etc/shadow by using the standard passwd command, and then adding their password a second time in the /etc/smbpasswd Samba password file by running the smbpasswd command), or by delegating authentication to an NT server (security = [ server | domain ].

Another, less-satisfactory solution is to force those Windows hosts to send the user's password in clear-text. For this, edit the following key in the Registry:

	[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\VNETSUP]
	" EnablePlainTextPassword"=dword:00000001

Keeping smbpasswd and /etc/shadow in sync

You can have Samba update /etc/shadow when you run smbpasswd to set a new password: Just add
        unix password sync = yes
        passwd program = /usr/bin/passwd %u
Note: Make sure you use the correct path to passwd .

Using Samba as time server

By default, Samba will not advertize itself as a time server. To change this, time server = True. To synchronized Windows clients, open a DOS box, and run NET TIME \\SAMBA /yes /set. To keep the Samba server in sync, you should install NTP.

Resolving NetBIOS names

To resolve names, consider setting up an SMB host as WINS server. If there is an NT PDC available, you might want to set it up that way (and set Samba to wins server = MYPDC.) Otherwise, Samba can act as WINS server by setting wins support = yes. Remember to set name resolve = wins lmhosts hosts bcast since the default is lmhosts host wins bcast.

Browsing, a.k.a. Network Neighborhood

Browsing enables users to locate shared resources on the network. The browsing list is what appears when either running "net view" in a DOS box, and opening Network Neighborhood in Windows. 

Each subnet runs a Local Master Browser. Those lists are uploaded to a Domain Master Browser, which Local Master Browsers queries to download a complete, up-to-date list of hosts available. For synchronization to occur, use remote announce = . If your network has several sub-nets (and routers do not forward broadcasts), you must have a host acting as WINS server so that clients can resolve their NetBIOS name into IP addresses.

Note that an NT PDC will always be the Domain Master Browser for a domain, so it's not a good idea to set a Samba server to become one (ie. do not use domain master = yes if an NT PDC is available in your domain.) To allow the Samba to participate in the election to become the Local Master Browser, set local master = yes. Although not recommended, if you want Samba to win against NT Servers, set os level = 65.

(CHECK) To find out which host is the Local Master Browser (ie. registered resource __MSBROWSE__ <01> for the domain), run #nmblookup SIMPLE#01 .

(CHECK) To find out which host is the Domain Master Browser (ie. registered resource <1B> for the domain), run #nmblookup SIMPLE#1B .

Note that in a Windows 2000 environment, browsing has been replaced with Active Directory, and has been kept only for backwards compatibility.

Smbclient

To list shares ("services") available on a remote host, run smbclient $host -U test%tttttttt-R wins -L

Instant Messaging, a.k.a. WinPopUp/net send

To tell Samba to run a program when it receives a WinPopUp-style message, set eg. message command = csh -c ´xedit %s;rm %s´ &. To send an instant message to an SMB host, run smbclient -M REMOTEHOST, type your message, followed by CTRL-D.

Backing up remote Windows hosts with Samba

Smbtar

To connect to remote hosts, and back up selected files on a local tape drive (Doesn't recurse)
	for host in `cat ./hosts.txt`
	do
		smbtar -s $host -u test%tttttttt -x backup -d / -t /dev/tape -v *.c *.cpp *.h
	done
	

Smbclient

Downloading files into a directory

smbclient does not provide support for filtering through file extensions or specifying the tape drive to use as output. For this, use smbtar instead, which is just a shell script acting as front-end to smbclient. Note: Use -d to reach a given sub-directory (ie. -x backup/mysubdir won't work)
	#!/bin/bash
	#------- Remove old log files
	if [ -f ./log.txt ]
	then
	        mv ./log.txt ./log.txt.prev
	fi
	
	if [ -f ./log.err.txt ]
	then
	        mv ./log.err.txt ./log.err.txt.prev
	fi
	
	exec >./log.txt 2>./log.err.txt
	
	#----------- Start copying
	if [ ! -d ./AcmeBackup ]
	then
	        mkdir ./AcmeBackup
	fi 
	
	cd ./AcmeBackup
	
	for host in `cat ../acme.txt`
	do
	        if [ ! -d ./$host ]
	        then
	                mkdir ./$host
	        fi 
	
	        cd ./$host
	
	        echo Started backing up $host at `date`
	
	        smbclient //$host/backup -U BackupExec%password -R wins << EOF > /dev/null
	        prompt off
	        recurse
	
	        mask *.c
	        mget *
	
	        mask *.cpp
	        mget *
	
	        mask *.h
	        mget *
	
	        exit
	EOF
	
	        echo Back up of $host ended at `date`
	
	        cd ..
	
	done
	

Downloading files into a tarball

smbclient $host/backup -U BackupExec%password -R wins -Tc ./test.tar

Mounting remote SMB shares

mount -t smbfs -o username=jdoe,password=password //ffaure/software /mnt/ff

Setting up Windows hosts with NetBeui and TCP/IP

It is not recommended to keep both protocols, especially if NetBeui is set as the primary protocol, because it slows down browsing (Windows sends browsing requests through its primary protocol first, and, if unsuccessful, only tries other protocols after a time-out.)

Moving from Samba 3 to Samba 4

Q&A

Why can I copy/delete a file on an SD card, but not overwrite?

If the SD card is formatted in VFAT(FAT32), it's because it doesn't support Linux access rights: They are set through the settings in /etc/fstab.

Syslog complains with "At this time the 'samba' binary should only be used for either"

# systemctl disable samba-ad-dc

# systemctl enable samba nmbd.service smbd.service

How to force new files to be 644?

Don't know which does the trick, but this works:

force create mode = 0644

create mask = 0664

security mask = 0664

force security mode = 0664

readonly vs. writable? guest ok vs. public?

"readonly=no" and "writ(e)able=yes" mean the same thing.

Likewise for "guest ok = yes" and "public = yes".

If "security=share option is deprecated", how to build a free-for-all share?

Just add those two lines to enable anyone to read/write files in a share without being prompted for a login/password:

security = user
map to guest = Bad User

Unable to connect to CUPS server localhost:631 - Connection refused

If the server will not handle printers, add "printing = bsd" and "printcap name = /dev/null" to get rid of this warning in the log:

Unable to connect to CUPS server localhost:631 - Connection refused
failed to retrieve printer list: NT_STATUS_UNSUCCESSFUL

How to make network browsing work with two Samba hosts on the LAN?

After adding a second Samba server on the same LAN with no browser-related settings, I reconfigured the second host thusly:

[global]
...
netbios name = UBUNTU
 
wins support = yes
domain master = yes
local master = yes
preferred master = yes
os level = 255

... and the first host thusly:

local master = no

Reload nmbd on the new domain/local master and check that it won the election.

How to sync Windows login + passwd with Linux?

Which user.group does Samba use to run?

Just run "/etc/init.d/smbd start" and "/etc/init.d/nmbd start", followed by "ps aux | grep mbd" to check

How to tell Samba to run under a non-root user?

It's not possible, as Samba must bind to priviledged ports anyway. Also, Samba must run as root so it can change the Euid of the process to perform some operations.

Running Samba as chroot is a good way to run Samba securely.

What happens if the Windows account doesn't exist on Samba?

;reason to handle unknown user

;other possible reasons: never, bad password, bad uid

map to guest = bad user

;allow guest account

guest ok = yes

;which guest account to use instead

guest account = smbguest

Samba-TNG? LikeWise?

Samba-TNG is a fork of Samba that occured in 2000, but seems to have not achieved much.

Likewise is a dual-licensed that lets a Unix server be part of a Windows Active Directory and thus, delegates authentication. Apparently, it also includes a full alternative to Samba as SMB/CIFS server.

Likewise, I'm Sure - After the dust settled, it turns out that Samba and Likewise can co-exist after all.

CEO Perspective: History Behind Likewise-CIFS

What do those error messages mean?

  • smbd/files.c:file_init(193) file_init: Information only: requested 10000 open files, 5401 are available.
  • smbd/server.c:open_sockets_smbd(527) open_sockets_smbd: accept: Software caused connection abort
  • lib/util_sock.c:get_peer_addr(1232) getpeername failed. Error was Socket is not connected

How to hide Unix .files?

"hide dot files = no" works but the files will still be displayed in Windows if the user configured his Windows Explorer options to show hidden files. The solution is to use this:
veto files = /.??*/

When connecting to a Samba share, I'm prompted for a password for user IPC$

You have set up Samba to run in either security=share or security=user, and you are running either 95B (a.k.a. OSR2), NT4 SP3, or W2K, which send passwords encrypted. Other versions of Windows send passwords in clear text.
To solve this problem, you must set up Samba to keep a second database of user acounts with compatible hashed passwords (Note: You must set a password in Windows. Simply hitting ENTER won't do):
  1. If not done already, run useradd jdoe to create a matching user account on the Samba server
  2. In smb.conf, go to the [global] section, and add encrypt password=yes
  3. smbpasswd -a jdoe (where jdoe must have been created above with useradd)
 

Voilà! User jdoe has an account on the Samba server (/etc/password), an MD5-hashed password (/etc/shadow), and his password is also available in Samba's database /etc/smbpasswd to keep Windows happy.

What is the difference between security=share and security=user?

security=share is deprecated anyway.

Removing a computer account

As root, run smbpasswd -x w2kclient$

Checking connection to Samba

Open a DOS box, and run "net use \\mylinux\ipc$ /user:jdoe", where jdoe is the user account that you created above

Mapping a drive letter to a Samba share

Open a DOS box, and run "net use x: \\mylinux\jdoe". If you are not logged on as user jdoe on the Windows host, run "net use x: \\mylinux\jdoe /user:jdoe", and type jdoe's password as entered when you ran smbpasswd to create this user's encrypted password

Removing a drive letter

net use x: /d

Finding which host is running as local master browser

On a host running Samba, type nmblookup -M - (or nmblookup -M MYDOMAIN)

Resources

Books

Sites

Temp stuff