On Fri, Sep 09, 2011 at 07:06:47PM -0400, Simo Sorce wrote:
> On Thu, 2011-09-08 at 14:39 +0200, Sumit Bose wrote:
> > On Thu, Sep 08, 2011 at 02:06:44PM +0200, Martin Kosek wrote:
> > > On Thu, 2011-09-08 at 13:52 +0200, Sumit Bose wrote:
> > > > On Wed, Sep 07, 2011 at 06:10:50PM -0400, Simo Sorce wrote:
> > > > > On Tue, 2011-08-30 at 16:40 +0200, Sumit Bose wrote:
> > > > > > I don't think that we should run winbind.
> > > > > > 
> > > > > > I also changed the path to the smb.conf file from /etc/ipa
> > > > > > to /etc/samba
> > > > > > which makes the change to /etc/sysconfig/samba unnecessary.
> > > > > > 
> > > > > > Thanks for review.
> > > > > > 
> > > > > Ok tested this today, after I was able to tame my machine.
> > > > > 
> > > > > Some issues and comments still.
> > > > > 
> > > > > 1) If you just run ipa-adtrust-install it throws an error about an
> > > > > Illegal netbios name and quits. That's not right, as it should ask for
> > > > > the netbios name if one is not provided on the command line 
> > > > > presenting a
> > > > > default option (based on the last domain component uppercased maybe),
> > > > 
> > > > fixed
> > > > 
> > > > > 
> > > > > 2) I see the way you write the temp smb.conf is by using a lot of
> > > > > fd.write() calls. It would be much easier instead to use the 
> > > > > templating
> > > > > engine we use elsewhere in the code and drop a template file in
> > > > > install/share, this will allow us to easily tweak the initial
> > > > > installation options w/o touching the python code every time.
> > > > 
> > > > fixed
> > > > 
> > > > new version attached.
> > > > 
> > > > bye,
> > > > Sumit
> > > > 
> > > > > 
> > > > > 3) Everything installed and started but my smbd coredump immediately
> > > > > after. It is almost certainly not a problem in your patch though :-)
> > > > > 
> > > > > So jokes aside if you fix 1 and 2 I think we can push to master.
> > > > > 
> > > > > Simo.
> > > > > 
> > > > > -- 
> > > > > Simo Sorce * Red Hat, Inc * New York
> > > > > 
> > > 
> > > Only one nitpick from me. The new man page header should be changed
> > > according to our last man page consolidation effort in ticket 1687 so
> > > that it is consistent with the others. In your case, the header should
> > > be:
> > > 
> > > +.TH "ipa-adtrust-install" "1" "Aug 23 2011" "FreeIPA" "FreeIPA Manual 
> > > Pages"
> > > 
> > > Plus, --netbios-name option is not covered in the man page.
> > 
> > Thank you for the feedback, I fixed it accordingly. New version
> > attached.
> 
> NACK
> 
> Ok I spent an afternoon with gd's packages trying to get the install
> work.
> I have it finally start smbd if run manually.
> 
> Quite a few things needed to be changed in the configuration to get it
> to start smbd (not a working solution yet though).
> 
> First of all for some reason passdb backend would use the hostname
> instead of the ldapi socket. This seem to be fixed in the latest patch
> (the install had been done with the previous)

yes, was already fixed

> 
> - ldap ssl need to set to off, as dirsrv does not allow (nor we want) to
> use start tls on ldapi
> I had to use: net conf setparms global 'ldap ssl' off

fixed

> 
> - ldap suffix = cn=accounts,dc=ipa,dc=test is definitely not right.
> This is not fixed in the current patch either.
> 
> It should be ldap suffix = $SUFFIX

fixed

> 
> - log file directive is unusual %d causes each log file to be created
> with the pid number, that is very annoying when you want to see the logs
> of a specific machine, please change it to use %m

fixed

> 
> - No service principal is created for cifs/fqdn

fixed

> 
> - No directive to tell samba to use the system keytab. you should
> probably set 'kerberos method = system keytab'
> 

fixed

> 
> I couldn't test everything due to other issues I found and need to
> investigate in both the samba packaghes and krb5kdc segfaulting on me
> when I try to use smbclient -k yes :-(

I can now run 'smbclient -k -L' on my test system wit hthe recent samba
patch.

bye,
Sumit

> 
> Simo.
> 
> -- 
> Simo Sorce * Red Hat, Inc * New York
> 
From d321445103df0ce185be30e31fb88d70724aefb6 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Wed, 7 Sep 2011 10:17:12 +0200
Subject: [PATCH] Add ipa-adtrust-install utility

https://fedorahosted.org/freeipa/ticket/1619
---
 freeipa.spec.in                                  |    2 +
 install/po/Makefile.in                           |    1 +
 install/share/Makefile.am                        |    1 +
 install/share/smb.conf.template                  |   28 +++
 install/tools/Makefile.am                        |    1 +
 install/tools/ipa-adtrust-install                |  244 ++++++++++++++++++++
 install/tools/man/Makefile.am                    |    1 +
 install/tools/man/ipa-adtrust-install.1          |   47 ++++
 ipaserver/install/Makefile.am                    |    1 +
 ipaserver/install/service.py                     |    3 +-
 ipaserver/install/smbinstance.py                 |  269 ++++++++++++++++++++++
 tests/test_ipaserver/install/test_smbinstance.py |   59 +++++
 12 files changed, 656 insertions(+), 1 deletions(-)
 create mode 100644 install/share/smb.conf.template
 create mode 100755 install/tools/ipa-adtrust-install
 create mode 100644 install/tools/man/ipa-adtrust-install.1
 create mode 100644 ipaserver/install/smbinstance.py
 create mode 100755 tests/test_ipaserver/install/test_smbinstance.py

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 
fc7141cc1729b751e09f8fc8dfdd1c8d94756359..2aa90a8c45efb1d2b8978b5d98e3afb22b2a71df
 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -401,6 +401,7 @@ fi
 %doc COPYING README Contributors.txt
 %{_sbindir}/ipa-ca-install
 %{_sbindir}/ipa-dns-install
+%{_sbindir}/ipa-adtrust-install
 %{_sbindir}/ipa-server-install
 %{_sbindir}/ipa-replica-conncheck
 %{_sbindir}/ipa-replica-install
@@ -482,6 +483,7 @@ fi
 %{_mandir}/man1/ipa-server-certinstall.1.gz
 %{_mandir}/man1/ipa-server-install.1.gz
 %{_mandir}/man1/ipa-dns-install.1.gz
+%{_mandir}/man1/ipa-adtrust-install.1.gz
 %{_mandir}/man1/ipa-ca-install.1.gz
 %{_mandir}/man1/ipa-compat-manage.1.gz
 %{_mandir}/man1/ipa-nis-manage.1.gz
diff --git a/install/po/Makefile.in b/install/po/Makefile.in
index 
47c8bbba56041f95fc6641ff0188ab60db658de8..ac08b47921c0a96d0fe06b8d8f1419d7cd76bd36
 100644
--- a/install/po/Makefile.in
+++ b/install/po/Makefile.in
@@ -51,6 +51,7 @@ PY_EXPLICIT_FILES = \
      install/tools/ipa-server-install \
      install/tools/ipa-ldap-updater \
      install/tools/ipa-dns-install \
+     install/tools/ipa-adtrust-install \
      install/tools/ipa-ca-install \
      ipa-client/ipa-install/ipa-client-install
 
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 
f2a6a6cae418b2f31151130c4fd53db8cbbe922a..50ec816b42fcbad619504bf3ccf6ef293e5188ba
 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -32,6 +32,7 @@ app_DATA =                            \
        krb.con.template                \
        krbrealm.con.template           \
        preferences.html.template       \
+       smb.conf.template               \
        referint-conf.ldif              \
        dna.ldif                        \
        master-entry.ldif               \
diff --git a/install/share/smb.conf.template b/install/share/smb.conf.template
new file mode 100644
index 
0000000000000000000000000000000000000000..a7fc10691e8a4dd69b711d266f6bb70479dd319d
--- /dev/null
+++ b/install/share/smb.conf.template
@@ -0,0 +1,28 @@
+[global]
+workgroup = $NETBIOS_NAME
+realm = $REALM
+kerberos method = system keytab
+create krb5 conf = no
+security = user
+domain master = yes
+domain logons = yes
+log level = 1
+max log size = 100000
+log file = /var/log/samba/log.%m
+passdb backend = IPA_ldapsam:ldapi://$LDAPI_SOCKET
+ldapsam:trusted=yes
+ldap ssl = off
+ldap admin dn = $SMB_DN
+ldap suffix = $SUFFIX
+ldap user suffix = cn=users,cn=accounts
+ldap group suffix = cn=groups,cn=accounts
+ldap machine suffix = cn=computers,cn=accounts
+rpc_server:epmapper = external
+rpc_server:lsarpc = external
+rpc_server:lsass = external
+rpc_server:lsasd = external
+rpc_server:samr = external
+rpc_server:netlogon = external
+rpc_server:tcpip = yes
+rpc_daemon:epmd = fork
+rpc_daemon:lsasd = fork
diff --git a/install/tools/Makefile.am b/install/tools/Makefile.am
index 
fc615ec04f324c2d9c98dc8cf674938e1064bec6..96da7531764598878f94b6abd54c27a74671c028
 100644
--- a/install/tools/Makefile.am
+++ b/install/tools/Makefile.am
@@ -8,6 +8,7 @@ sbin_SCRIPTS =                  \
        ipa-ca-install          \
        ipa-dns-install         \
        ipa-server-install      \
+       ipa-adtrust-install     \
        ipa-replica-conncheck   \
        ipa-replica-install     \
        ipa-replica-prepare     \
diff --git a/install/tools/ipa-adtrust-install 
b/install/tools/ipa-adtrust-install
new file mode 100755
index 
0000000000000000000000000000000000000000..86c69ca459026a0fd91ab196461cd63547f7ca57
--- /dev/null
+++ b/install/tools/ipa-adtrust-install
@@ -0,0 +1,244 @@
+#! /usr/bin/python
+#
+# Authors: Sumit Bose <sb...@redhat.com>
+# Based on ipa-server-install by Karl MacMillan <kmacmil...@mentalrootkit.com>
+# and ipa-dns-install by Martin Nagy
+#
+# Copyright (C) 2011  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import traceback
+
+from ipaserver.plugins.ldap2 import ldap2
+from ipaserver.install import smbinstance
+from ipaserver.install.installutils import *
+from ipaserver.install import installutils
+from ipapython import version
+from ipapython import ipautil, sysrestore
+from ipalib import api, errors, util
+from ipapython.config import IPAOptionParser
+import krbV
+import ldap
+
+def parse_options():
+    parser = IPAOptionParser(version=version.VERSION)
+    parser.add_option("-p", "--ds-password", dest="dm_password",
+                      sensitive=True, help="directory manager password")
+    parser.add_option("-d", "--debug", dest="debug", action="store_true",
+                      default=False, help="print debugging information")
+    parser.add_option("--ip-address", dest="ip_address",
+                      type="ip", ip_local=True, help="Master Server IP 
Address")
+    parser.add_option("--netbios-name", dest="netbios_name",
+                      help="NetBIOS name of the IPA domain")
+    parser.add_option("-U", "--unattended", dest="unattended", 
action="store_true",
+                      default=False, help="unattended installation never 
prompts the user")
+
+    options, args = parser.parse_args()
+    safe_options = parser.get_safe_opts(options)
+
+    return safe_options, options
+
+def netbios_name_error(name):
+    print "Illegal NetBIOS name [%s].\n" % name
+    print "Up to 15 characters and only uppercase ASCII letter and digits are 
allowed."
+
+def read_netbios_name(netbios_default):
+    netbios_name = ""
+
+    print "Enter the NetBIOS name for the IPA domain."
+    print "Only up to 15 uppercase ASCII letters and digits are allowed."
+    print "Example: EXAMPLE."
+    print ""
+    print ""
+    if not netbios_default:
+        netbios_default = "EXAMPLE"
+    while True:
+        netbios_name = ipautil.user_input("NetBIOS domain name", 
netbios_default, allow_empty = False)
+        print ""
+        if smbinstance.check_netbios_name(netbios_name):
+            break
+
+        netbios_name_error(netbios_name)
+
+    return netbios_name
+
+def main():
+    safe_options, options = parse_options()
+
+    if os.getegid() != 0:
+        sys.exit("Must be root to setup AD trusts on server")
+
+    installutils.check_server_configuration()
+
+    standard_logging_setup("/var/log/ipaserver-install.log", options.debug, 
filemode='a')
+    print "\nThe log file for this installation can be found in 
/var/log/ipaserver-install.log"
+
+    logging.debug('%s was invoked with options: %s' % (sys.argv[0], 
safe_options))
+    logging.debug("missing options might be asked for interactively later\n")
+
+    global fstore
+    fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
+
+    print 
"=============================================================================="
+    print "This program will setup components needed to establish trust to AD 
domains for"
+    print "the FreeIPA Server."
+    print ""
+    print "This includes:"
+    print "  * Configure Samba"
+    print "  * Add trust related objects to FreeIPA LDAP server"
+    #TODO:
+    #print "  * Add a SID to all users and Posix groups"
+    print ""
+    print "To accept the default shown in brackets, press the Enter key."
+    print ""
+
+    # Check if samba packages are installed
+    if not smbinstance.check_inst(options.unattended):
+        sys.exit("Aborting installation.")
+
+    # Initialize the ipalib api
+    cfg = dict(
+        in_server=True,
+        debug=options.debug,
+    )
+    api.bootstrap(**cfg)
+    api.finalize()
+
+    if smbinstance.ipa_smb_conf_exists():
+        sys.exit("Aborting installation.")
+
+    # Check we have a public IP that is associated with the hostname
+    try:
+        if options.ip_address:
+            ip = ipautil.CheckedIPAddress(options.ip_address, match_local=True)
+        else:
+            hostaddr = resolve_host(api.env.host)
+            ip = hostaddr and ipautil.CheckedIPAddress(hostaddr, 
match_local=True)
+    except Exception, e:
+        print "Error: Invalid IP Address %s: %s" % (ip, e)
+        ip = None
+
+    if not ip:
+        if options.unattended:
+            sys.exit("Unable to resolve IP address for host name")
+        else:
+            read_ip = read_ip_address(api.env.host, fstore)
+            try:
+                ip = ipautil.CheckedIPAddress(read_ip, match_local=True)
+            except Exception, e:
+                print "Error: Invalid IP Address %s: %s" % (ip, e)
+                sys.exit("Aborting installation.")
+
+    ip_address = str(ip)
+    logging.debug("will use ip_address: %s\n", ip_address)
+
+    if not options.unattended:
+        print ""
+        print "The following operations may take some minutes to complete."
+        print "Please wait until the prompt is returned."
+        print ""
+
+    # Create a Samba instance
+    if options.unattended and not options.dm_password:
+        sys.exit("\nIn unattended mode you need to provide at least the -p 
option")
+
+    netbios_name = options.netbios_name
+    if not netbios_name:
+        netbios_name = smbinstance.make_netbios_name(api.env.domain)
+
+    if not smbinstance.check_netbios_name(netbios_name):
+        if options.unattended:
+            netbios_name_error(netbios_name)
+            sys.exit("Aborting installation.")
+        else:
+            netbios_name = None
+            if options.netbios_name:
+                netbios_name_error(options.netbios_name)
+
+    if not options.unattended and ( not netbios_name or not 
options.netbios_name):
+        netbios_name = read_netbios_name(netbios_name)
+
+    dm_password = options.dm_password or read_password("Directory Manager",
+                                             confirm=False, validate=False)
+    smb = smbinstance.SMBInstance(fstore, dm_password)
+
+    # try the connection
+    try:
+        smb.ldap_connect()
+        smb.ldap_disconnect()
+    except ldap.INVALID_CREDENTIALS, e:
+        sys.exit("Password is not valid!")
+
+    if smb.dm_password:
+        api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", 
bind_pw=smb.dm_password)
+    else:
+        # See if our LDAP server is up and we can talk to it over GSSAPI
+        ccache = krbV.default_context().default_ccache().name
+        api.Backend.ldap2.connect(ccache)
+
+    smb.setup(api.env.host, ip_address, api.env.realm, api.env.domain,
+              netbios_name)
+    smb.create_instance()
+
+    print 
"=============================================================================="
+    print "Setup complete"
+    print ""
+    print "\tYou must make sure these network ports are open:"
+    print "\t\tTCP Ports:"
+    print "\t\t  * 138: netbios-dgm"
+    print "\t\t  * 139: netbios-ssn"
+    print "\t\t  * 445: microsoft-ds"
+    print "\t\tUDP Ports:"
+    print "\t\t  * 138: netbios-dgm"
+    print "\t\t  * 139: netbios-ssn"
+    print "\t\t  * 445: microsoft-ds"
+    print ""
+    print "\tAdditionally you have to make sure the FreeIPA LDAP server cannot 
reached"
+    print "\tby any domain controller in the Active Directory domain by 
closing the"
+    print "\tfollowing ports for these servers:"
+    print "\t\tTCP Ports:"
+    print "\t\t  * 389, 636: LDAP/LDAPS"
+    print "\t\tUDP Ports:"
+    print "\t\t  * 389: (C)LDAP"
+    print "\tYou may want to choose to REJECT the network packets instead of 
DROPing them"
+    print "\tto avoid timeouts on the AD domain controllers."
+
+    return 0
+
+try:
+    sys.exit(main())
+except SystemExit, e:
+    sys.exit(e)
+except KeyboardInterrupt:
+    print "Installation cancelled."
+except RuntimeError, e:
+    print str(e)
+except HostnameLocalhost:
+    print "The hostname resolves to the localhost address (127.0.0.1/::1)"
+    print "Please change your /etc/hosts file so that the hostname"
+    print "resolves to the ip address of your network interface."
+    print "The KDC service does not listen on localhost"
+    print ""
+    print "Please fix your /etc/hosts file and restart the setup program"
+except Exception, e:
+    message = "Unexpected error - see ipaserver-install.log for details:\n %s" 
% str(e)
+    print message
+    message = str(e)
+    for str in traceback.format_tb(sys.exc_info()[2]):
+        message = message + "\n" + str
+    logging.debug(message)
+    sys.exit(1)
diff --git a/install/tools/man/Makefile.am b/install/tools/man/Makefile.am
index 
71d9b29c87d2b24c51d3048dc1050e099a89835d..d5b5976b0fd8c8e6683d09e7ade575fda2527832
 100644
--- a/install/tools/man/Makefile.am
+++ b/install/tools/man/Makefile.am
@@ -13,6 +13,7 @@ man1_MANS =                           \
        ipa-server-certinstall.1        \
        ipa-server-install.1            \
        ipa-dns-install.1               \
+       ipa-adtrust-install.1           \
        ipa-ca-install.1                \
        ipa-ldap-updater.1              \
        ipa-compat-manage.1             \
diff --git a/install/tools/man/ipa-adtrust-install.1 
b/install/tools/man/ipa-adtrust-install.1
new file mode 100644
index 
0000000000000000000000000000000000000000..a3981adf48d14cc0e540c646fff099490203f862
--- /dev/null
+++ b/install/tools/man/ipa-adtrust-install.1
@@ -0,0 +1,47 @@
+.\" A man page for ipa-adtrust-install
+.\" Copyright (C) 2011 Red Hat, Inc.
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, either version 3 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License
+.\" along with this program.  If not, see <http://www.gnu.org/licenses/>.
+.\"
+.\" Author: Sumit Bose <sb...@redhat.com>
+.\"
+.TH "ipa-adtrust-install" "1" "Aug 23 2011" "FreeIPA" "FreeIPA Manual Pages"
+.SH "NAME"
+ipa\-adtrust\-install \- Prepare an IPA server to be able to establish trust 
relationships with AD domains
+.SH "SYNOPSIS"
+ipa\-adtrust\-install [\fIOPTION\fR]...
+.SH "DESCRIPTION"
+Adds all necesary objects and configuration to allow an IPA server to create a
+trust to an Active Directory domain. This requires that the IPA server is
+already installed and configured.
+.SH "OPTIONS"
+.TP
+\fB\-p\fR \fIDM_PASSWORD\fR, \fB\-\-ds\-password\fR=\fIDM_PASSWORD\fR
+The password to be used by the Directory Server for the Directory Manager user
+.TP
+\fB\-d\fR, \fB\-\-debug\fR
+Enable debug logging when more verbose output is needed
+.TP
+\fB\-\-ip\-address\fR=\fIIP_ADDRESS\fR
+The IP address of the IPA server. If not provided then this is determined 
based on the hostname of the server.
+.TP
+\fB\-\-netbios\-name\fR=\fINETBIOS_NAME\fR
+The NetBIOS name for the IPA domain. If not provided then this is determined 
based on the leading component of the DNS domain name.
+.TP
+\fB\-U\fR, \fB\-\-unattended\fR
+An unattended installation that will never prompt for user input
+.SH "EXIT STATUS"
+0 if the installation was successful
+
+1 if an error occurred
diff --git a/ipaserver/install/Makefile.am b/ipaserver/install/Makefile.am
index 
8932eadbb7ace71372277259a557884d989ea2c1..398551bd78aa4ba893a3953f0c7ee7bcb23d1a14
 100644
--- a/ipaserver/install/Makefile.am
+++ b/ipaserver/install/Makefile.am
@@ -10,6 +10,7 @@ app_PYTHON =                  \
        krbinstance.py          \
        httpinstance.py         \
        ntpinstance.py          \
+       smbinstance.py          \
        service.py              \
        installutils.py         \
        replication.py          \
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 
2f80749ade535ff24cbacd90f8c03699432f3186..5f7260e2343e9d9373ff4cfd8d071b82f218ed33
 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -37,7 +37,8 @@ SERVICE_LIST = {
     'KPASSWD':('kadmin', 20),
     'DNS':('named', 30),
     'HTTP':('httpd', 40),
-    'CA':('pki-cad', 50)
+    'CA':('pki-cad', 50),
+    'ADTRUST':('smb', 60)
 }
 
 def stop(service_name, instance_name="", capture_output=True):
diff --git a/ipaserver/install/smbinstance.py b/ipaserver/install/smbinstance.py
new file mode 100644
index 
0000000000000000000000000000000000000000..a6caca8bb995ea58fee895d5bd395c30b8204557
--- /dev/null
+++ b/ipaserver/install/smbinstance.py
@@ -0,0 +1,269 @@
+# Authors: Sumit Bose <sb...@redhat.com>
+#
+# Copyright (C) 2011  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import logging
+
+import os
+import ldap
+import service
+import tempfile
+import installutils
+from ipaserver import ipaldap
+from ipaserver.install.dsinstance import realm_to_serverid
+from ipalib import errors
+from ipapython import sysrestore
+from ipapython import ipautil
+
+import random
+import string
+import struct
+
+allowed_netbios_chars = string.ascii_uppercase + string.digits
+
+def check_inst(unattended):
+    has_smb = True
+
+    if not os.path.exists('/usr/sbin/smbd'):
+        print "Samba was not found on this system"
+        print "Please install the 'samba' package and start the installation 
again"
+        has_smb = False
+
+    #TODO: Add check for needed samba4 libraries
+
+    return has_smb
+
+def ipa_smb_conf_exists():
+    fd = open('/etc/samba/smb.conf', 'r')
+    lines = fd.readlines()
+    fd.close()
+    for line in lines:
+        if line.startswith('### Added by IPA Installer ###'):
+            return True
+    return False
+
+
+def check_netbios_name(s):
+    # NetBIOS names may not be longer than 15 allowed characters
+    if not s or len(s) > 15 or ''.join([c for c in s if c not in 
allowed_netbios_chars]):
+        return False
+
+    return True
+
+def make_netbios_name(s):
+    return ''.join([c for c in s.split('.')[0].upper() if c in 
allowed_netbios_chars])[:15]
+
+class SMBInstance(service.Service):
+    def __init__(self, fstore=None, dm_password=None):
+        service.Service.__init__(self, "smb", dm_password=dm_password)
+
+        if fstore:
+            self.fstore = fstore
+        else:
+            self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
+
+    def __create_samba_user(self):
+        print "The user for Samba is %s" % self.smb_dn
+        try:
+            self.admin_conn.getEntry(self.smb_dn, ldap.SCOPE_BASE)
+            print "Samba user entry exists, not resetting password"
+            return
+        except errors.NotFound:
+            pass
+
+        # The user doesn't exist, add it
+        entry = ipaldap.Entry(self.smb_dn)
+        entry.setValues("objectclass", ["account", "simplesecurityobject"])
+        entry.setValues("uid", "samba")
+        entry.setValues("userPassword", self.smb_dn_pwd)
+        self.admin_conn.add_s(entry)
+
+        # And finally grant it permission to read NT passwords, we do not want
+        # to support LM passwords so there is no need to allow access to them
+        mod = [(ldap.MOD_ADD, 'aci',
+            str(['(targetattr = "sambaNTPassword")(version 3.0; acl "Samba 
user can read NT passwords"; allow (read) userdn="ldap:///%s";;)' % 
self.smb_dn]))]
+        try:
+            self.admin_conn.modify_s(self.suffix, mod)
+        except ldap.TYPE_OR_VALUE_EXISTS:
+            logging.debug("samba user aci already exists in suffix %s on %s" % 
(self.suffix, self.admin_conn.host))
+
+    def __gen_sid_string(self):
+        sub_ids = struct.unpack("<LLL", os.urandom(12))
+        return "S-1-5-21-%d-%d-%d" % (sub_ids[0], sub_ids[1], sub_ids[2])
+
+    def __create_samba_domain_object(self):
+        trust_dn = "cn=trusts,%s" % self.suffix
+        smb_dom_dn = "cn=ad,%s" % trust_dn
+
+        try:
+            self.admin_conn.getEntry(smb_dom_dn, ldap.SCOPE_BASE)
+            print "Samba domain object already exists"
+            return
+        except errors.NotFound:
+            pass
+
+        try:
+            self.admin_conn.getEntry(trust_dn, ldap.SCOPE_BASE)
+        except errors.NotFound:
+            entry = ipaldap.Entry(trust_dn)
+            entry.setValues("objectclass", ["nsContainer"])
+            entry.setValues("cn", "trusts")
+            self.admin_conn.add_s(entry)
+
+        entry = ipaldap.Entry(smb_dom_dn)
+        entry.setValues("objectclass", ["sambaDomain", "nsContainer"])
+        entry.setValues("cn", "ad")
+        entry.setValues("sambaDomainName", self.netbios_name)
+        entry.setValues("sambaSID", self.__gen_sid_string())
+        #TODO: which MAY attributes do we want to set ?
+        self.admin_conn.add_s(entry)
+
+    def __write_smb_conf(self):
+        self.fstore.backup_file(self.smb_conf)
+
+        fd = open(self.smb_conf, "w")
+        fd.write('### Added by IPA Installer ###\n')
+        fd.write('[global]\n')
+        fd.write('config backend = registry\n')
+        fd.close()
+
+    def __write_smb_registry(self):
+        template = os.path.join(ipautil.SHARE_DIR, "smb.conf.template")
+        conf = ipautil.template_file(template, self.sub_dict)
+        [fd, tmp_name] = tempfile.mkstemp()
+        os.write(fd, conf)
+        os.close(fd)
+
+        args = ["/usr/bin/net", "conf", "import", tmp_name]
+
+        try:
+            ipautil.run(args)
+        finally:
+            os.remove(tmp_name)
+
+    def __set_smb_ldap_password(self):
+        args = ["/usr/bin/smbpasswd", "-c", self.smb_conf, "-s", "-W" ]
+
+        ipautil.run(args, stdin = self.smb_dn_pwd + "\n" + self.smb_dn_pwd + 
"\n" )
+
+    def __setup_principal(self):
+        cifs_principal = "cifs/" + self.fqdn + "@" + self.realm_name
+        installutils.kadmin_addprinc(cifs_principal)
+
+        self.move_service(cifs_principal)
+
+        try:
+            ipautil.run(["ipa-rmkeytab", "--principal", cifs_principal,
+                                         "-k", "/etc/krb5.keytab"])
+        except ipautil.CalledProcessError, e:
+            if e.returncode != 5:
+                logging.critical("Failed to remove old key for %s" % 
cifs_principal)
+
+        try:
+            ipautil.run(["ipa-getkeytab", "--server", self.fqdn,
+                                          "--principal", cifs_principal,
+                                          "-k", "/etc/krb5.keytab"])
+        except ipautil.CalledProcessError, e:
+            logging.critical("Failed to add key for %s" % cifs_principal)
+
+    def __start(self):
+        try:
+            self.start()
+        except:
+            logging.critical("smbd service failed to start")
+
+    def __stop(self):
+        self.backup_state("running", self.is_running())
+        try:
+            self.stop()
+        except:
+            pass
+
+    def __enable(self):
+        self.backup_state("enabled", self.is_enabled())
+        # We do not let the system start IPA components on its own,
+        # Instead we reply on the IPA init script to start only enabled
+        # components as found in our LDAP configuration tree
+        self.ldap_enable('ADTRUST', self.fqdn, self.dm_password, self.suffix)
+
+    def __setup_sub_dict(self):
+        self.sub_dict = dict(REALM = self.realm_name,
+                             SUFFIX = self.suffix,
+                             NETBIOS_NAME = self.netbios_name,
+                             SMB_DN = self.smb_dn,
+                             LDAPI_SOCKET = self.ldapi_socket)
+
+    def setup(self, fqdn, ip_address, realm_name, domain_name, netbios_name,
+              smbd_user="samba"):
+        self.fqdn =fqdn
+        self.ip_address = ip_address
+        self.realm_name = realm_name
+        self.domain_name = domain_name
+        self.netbios_name = netbios_name
+        self.smbd_user = smbd_user
+        self.suffix = ipautil.realm_to_suffix(self.realm_name)
+        self.ldapi_socket = "%%2fvar%%2frun%%2fslapd-%s.socket" % 
realm_to_serverid(self.realm_name)
+
+        self.smb_conf = "/etc/samba/smb.conf"
+
+        self.smb_dn = "uid=samba,cn=sysaccounts,cn=etc,%s" % self.suffix
+        self.smb_dn_pwd = ipautil.ipa_generate_password()
+
+        self.__setup_sub_dict()
+
+
+    def create_instance(self):
+
+        self.ldap_connect()
+
+        self.step("stopping smbd", self.__stop)
+        self.step("create samba user", self.__create_samba_user)
+        self.step("create samba domain object", 
self.__create_samba_domain_object)
+        self.step("create samba config registry", self.__write_smb_registry)
+        self.step("writing samba config file", self.__write_smb_conf)
+        self.step("setting password for the samba user", 
self.__set_smb_ldap_password)
+        self.step("Adding cifs Kerberos principal", self.__setup_principal)
+        self.step("configuring smbd to start on boot", self.__enable)
+        self.step("starting smbd", self.__start)
+
+        self.start_creation("Configuring smbd:")
+
+    def uninstall(self):
+        if self.is_configured():
+            self.print_msg("Unconfiguring %s" % self.service_name)
+
+        running = self.restore_state("running")
+        enabled = self.restore_state("enabled")
+
+        try:
+            self.stop()
+        except:
+            pass
+
+        for f in [self.smb_conf]:
+            try:
+                self.fstore.restore_file(f)
+            except ValueError, error:
+                logging.debug(error)
+                pass
+
+        if not enabled is None and not enabled:
+            self.chkconfig_off()
+
+        if not running is None and running:
+            self.start()
diff --git a/tests/test_ipaserver/install/test_smbinstance.py 
b/tests/test_ipaserver/install/test_smbinstance.py
new file mode 100755
index 
0000000000000000000000000000000000000000..ec015763ea2d4bfaaf7ff382fff4c6df6fd2e9b6
--- /dev/null
+++ b/tests/test_ipaserver/install/test_smbinstance.py
@@ -0,0 +1,59 @@
+# Authors:
+#   Sumit Bose <sb...@redhat.com>
+#
+# Copyright (C) 2011  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+Test `smbinstance`
+"""
+
+import os
+import nose
+
+from ipaserver.install import smbinstance
+
+class test_smbinstance:
+    """
+    Test `smbinstance`.
+    """
+
+    def test_make_netbios_name(self):
+        s = smbinstance.make_netbios_name("ABCDEF")
+        assert s == 'ABCDEF' and isinstance(s, str)
+        s = smbinstance.make_netbios_name(U"ABCDEF")
+        assert s == 'ABCDEF' and isinstance(s, unicode)
+        s = smbinstance.make_netbios_name("abcdef")
+        assert s == 'ABCDEF'
+        s = smbinstance.make_netbios_name("abc.def")
+        assert s == 'ABC'
+        s = smbinstance.make_netbios_name("abcdefghijklmnopqr.def")
+        assert s == 'ABCDEFGHIJKLMNO'
+        s = smbinstance.make_netbios_name("A!$%B&/()C=?+*D")
+        assert s == 'ABCD'
+        s = smbinstance.make_netbios_name("!$%&/()=?+*")
+        assert not s
+
+    def test_check_netbios_name(self):
+        assert smbinstance.check_netbios_name("ABCDEF")
+        assert not smbinstance.check_netbios_name("abcdef")
+        assert smbinstance.check_netbios_name("ABCDE12345ABCDE")
+        assert not smbinstance.check_netbios_name("ABCDE12345ABCDE1")
+        assert not smbinstance.check_netbios_name("")
+
+        assert smbinstance.check_netbios_name(U"ABCDEF")
+        assert not smbinstance.check_netbios_name(U"abcdef")
+        assert smbinstance.check_netbios_name(U"ABCDE12345ABCDE")
+        assert not smbinstance.check_netbios_name(U"ABCDE12345ABCDE1")
-- 
1.7.6

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to