%PDF- %PDF-
| Direktori : /usr/lib/python3/dist-packages/samba/netcmd/domain/auth/ |
| Current File : //usr/lib/python3/dist-packages/samba/netcmd/domain/auth/policy.py |
# Unix SMB/CIFS implementation.
#
# authentication silos - authentication policy management
#
# Copyright (C) Catalyst.Net Ltd. 2023
#
# Written by Rob van der Linde <rob@catalyst.net.nz>
#
# 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 samba.getopt as options
from samba.netcmd import Command, CommandError, Option, SuperCommand
from samba.netcmd.domain.models import AuthenticationPolicy
from samba.netcmd.domain.models.auth_policy import MIN_TGT_LIFETIME,\
MAX_TGT_LIFETIME, StrongNTLMPolicy
from samba.netcmd.domain.models.exceptions import ModelError
from samba.netcmd.validators import Range
class cmd_domain_auth_policy_list(Command):
"""List authentication policies on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--json", help="Output results in JSON format.",
dest="output_format", action="store_const", const="json"),
]
def run(self, ldap_url=None, sambaopts=None, credopts=None,
output_format=None):
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
# Authentication policies grouped by cn.
try:
policies = {policy.cn: policy.as_dict()
for policy in AuthenticationPolicy.query(ldb)}
except ModelError as e:
raise CommandError(e)
# Using json output format gives more detail.
if output_format == "json":
self.print_json(policies)
else:
for policy in policies.keys():
self.outf.write(f"{policy}\n")
class cmd_domain_auth_policy_view(Command):
"""View an authentication policy on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--name",
help="Name of authentication policy to view (required).",
dest="name", action="store", type=str),
]
def run(self, ldap_url=None, sambaopts=None, credopts=None, name=None):
if not name:
raise CommandError("Argument --name is required.")
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
try:
policy = AuthenticationPolicy.get(ldb, cn=name)
except ModelError as e:
raise CommandError(e)
# Check if authentication policy exists first.
if policy is None:
raise CommandError(f"Authentication policy {name} not found.")
# Display policy as JSON.
self.print_json(policy.as_dict())
class cmd_domain_auth_policy_create(Command):
"""Create an authentication policy on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--name", help="Name of authentication policy (required).",
dest="name", action="store", type=str),
Option("--description",
help="Optional description for authentication policy.",
dest="description", action="store", type=str),
Option("--protect",
help="Protect authentication silo from accidental deletion.",
dest="protect", action="store_true"),
Option("--unprotect",
help="Unprotect authentication silo from accidental deletion.",
dest="unprotect", action="store_true"),
Option("--audit",
help="Only audit authentication policy.",
dest="audit", action="store_true"),
Option("--enforce",
help="Enforce authentication policy.",
dest="enforce", action="store_true"),
Option("--strong-ntlm-policy",
help=f"Strong NTLM Policy ({StrongNTLMPolicy.choices_str()}).",
dest="strong_ntlm_policy", type="choice", action="store",
choices=StrongNTLMPolicy.get_choices(),
default="Disabled"),
Option("--user-tgt-lifetime",
help="Ticket-Granting-Ticket lifetime for user accounts.",
dest="user_tgt_lifetime", type=int, action="store",
validators=[Range(min=MIN_TGT_LIFETIME, max=MAX_TGT_LIFETIME)]),
Option("--user-allow-ntlm-auth",
help="Allow NTLM network authentication when user "
"is restricted to selected devices.",
dest="user_allow_ntlm_auth", action="store_true",
default=False),
Option("--service-tgt-lifetime",
help="Ticket-Granting-Ticket lifetime for service accounts.",
dest="service_tgt_lifetime", type=int, action="store",
validators=[Range(min=MIN_TGT_LIFETIME, max=MAX_TGT_LIFETIME)]),
Option("--service-allow-ntlm-auth",
help="Allow NTLM network authentication when service "
"is restricted to selected devices.",
dest="service_allow_ntlm_auth", action="store_true",
default=False),
Option("--computer-tgt-lifetime",
help="Ticket-Granting-Ticket lifetime for computer accounts.",
dest="computer_tgt_lifetime", type=int, action="store",
validators=[Range(min=MIN_TGT_LIFETIME, max=MAX_TGT_LIFETIME)]),
]
def run(self, ldap_url=None, sambaopts=None, credopts=None, name=None,
description=None, protect=None, unprotect=None, audit=None,
enforce=None, strong_ntlm_policy=None, user_tgt_lifetime=None,
user_allow_ntlm_auth=None, service_tgt_lifetime=None,
service_allow_ntlm_auth=None, computer_tgt_lifetime=None):
if not name:
raise CommandError("Argument --name is required.")
if protect and unprotect:
raise CommandError("--protect and --unprotect cannot be used together.")
if audit and enforce:
raise CommandError("--audit and --enforce cannot be used together.")
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
try:
policy = AuthenticationPolicy.get(ldb, cn=name)
except ModelError as e:
raise CommandError(e)
# Make sure authentication policy doesn't already exist.
if policy is not None:
raise CommandError(f"Authentication policy {name} already exists.")
# New policy object.
policy = AuthenticationPolicy(
cn=name,
description=description,
strong_ntlm_policy=StrongNTLMPolicy[strong_ntlm_policy.upper()],
user_allow_ntlm_auth=user_allow_ntlm_auth,
user_tgt_lifetime=user_tgt_lifetime,
service_allow_ntlm_auth=service_allow_ntlm_auth,
service_tgt_lifetime=service_tgt_lifetime,
computer_tgt_lifetime=computer_tgt_lifetime,
)
# Either --enforce will be set or --audit but never both.
# The default if both are missing is enforce=True.
if enforce is not None:
policy.enforced = enforce
else:
policy.enforced = not audit
# Create policy.
try:
policy.save(ldb)
if protect:
policy.protect(ldb)
except ModelError as e:
raise CommandError(e)
# Authentication policy created successfully.
self.outf.write(f"Created authentication policy: {name}\n")
class cmd_domain_auth_policy_modify(Command):
"""Modify authentication policies on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--name", help="Name of authentication policy (required).",
dest="name", action="store", type=str),
Option("--description",
help="Optional description for authentication policy.",
dest="description", action="store", type=str),
Option("--protect",
help="Protect authentication silo from accidental deletion.",
dest="protect", action="store_true"),
Option("--unprotect",
help="Unprotect authentication silo from accidental deletion.",
dest="unprotect", action="store_true"),
Option("--audit",
help="Only audit authentication policy.",
dest="audit", action="store_true"),
Option("--enforce",
help="Enforce authentication policy.",
dest="enforce", action="store_true"),
Option("--strong-ntlm-policy",
help=f"Strong NTLM Policy ({StrongNTLMPolicy.choices_str()}).",
dest="strong_ntlm_policy", type="choice", action="store",
choices=StrongNTLMPolicy.get_choices()),
Option("--user-tgt-lifetime",
help="Ticket-Granting-Ticket lifetime for user accounts.",
dest="user_tgt_lifetime", type=int, action="store",
validators=[Range(min=MIN_TGT_LIFETIME, max=MAX_TGT_LIFETIME)]),
Option("--user-allow-ntlm-auth",
help="Allow NTLM network authentication when user "
"is restricted to selected devices.",
dest="user_allow_ntlm_auth", action="store_true",
default=False),
Option("--service-tgt-lifetime",
help="Ticket-Granting-Ticket lifetime for service accounts.",
dest="service_tgt_lifetime", type=int, action="store",
validators=[Range(min=MIN_TGT_LIFETIME, max=MAX_TGT_LIFETIME)]),
Option("--service-allow-ntlm-auth",
help="Allow NTLM network authentication when service "
"is restricted to selected devices.",
dest="service_allow_ntlm_auth", action="store_true",
default=False),
Option("--computer-tgt-lifetime",
help="Ticket-Granting-Ticket lifetime for computer accounts.",
dest="computer_tgt_lifetime", type=int, action="store",
validators=[Range(min=MIN_TGT_LIFETIME, max=MAX_TGT_LIFETIME)]),
]
def run(self, ldap_url=None, sambaopts=None, credopts=None, name=None,
description=None, protect=None, unprotect=None, audit=None,
enforce=None, strong_ntlm_policy=None, user_tgt_lifetime=None,
user_allow_ntlm_auth=None, service_tgt_lifetime=None,
service_allow_ntlm_auth=None, computer_tgt_lifetime=None):
if not name:
raise CommandError("Argument --name is required.")
if protect and unprotect:
raise CommandError("--protect and --unprotect cannot be used together.")
if audit and enforce:
raise CommandError("--audit and --enforce cannot be used together.")
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
try:
policy = AuthenticationPolicy.get(ldb, cn=name)
except ModelError as e:
raise CommandError(e)
# Check if authentication policy exists.
if policy is None:
raise CommandError(f"Authentication policy {name} not found.")
# Either --enforce will be set or --audit but never both.
if enforce:
policy.enforced = True
elif audit:
policy.enforced = False
# Update the description.
if description is not None:
policy.description = description
# User sign on
###############
if strong_ntlm_policy is not None:
policy.strong_ntlm_policy = \
StrongNTLMPolicy[strong_ntlm_policy.upper()]
if user_tgt_lifetime is not None:
policy.user_tgt_lifetime = user_tgt_lifetime
# Service sign on
##################
if service_tgt_lifetime is not None:
policy.service_tgt_lifetime = service_tgt_lifetime
# Computer
###########
if computer_tgt_lifetime is not None:
policy.computer_tgt_lifetime = computer_tgt_lifetime
# Update policy.
try:
policy.save(ldb)
if protect:
policy.protect(ldb)
elif unprotect:
policy.unprotect(ldb)
except ModelError as e:
raise CommandError(e)
# Authentication policy updated successfully.
self.outf.write(f"Updated authentication policy: {name}\n")
class cmd_domain_auth_policy_delete(Command):
"""Delete authentication policies on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--name", help="Name of authentication policy (required).",
dest="name", action="store", type=str),
Option("--force", help="Force delete protected authentication policy.",
dest="force", action="store_true")
]
def run(self, ldap_url=None, sambaopts=None, credopts=None, name=None,
force=None):
if not name:
raise CommandError("Argument --name is required.")
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
try:
policy = AuthenticationPolicy.get(ldb, cn=name)
except ModelError as e:
raise CommandError(e)
# Check if authentication policy exists first.
if policy is None:
raise CommandError(f"Authentication policy {name} not found.")
# Delete item, --force removes delete protection first.
try:
if force:
policy.unprotect(ldb)
policy.delete(ldb)
except ModelError as e:
if not force:
raise CommandError(
f"{e}\nTry --force to delete protected authentication policies.")
else:
raise CommandError(e)
# Authentication policy deleted successfully.
self.outf.write(f"Deleted authentication policy: {name}\n")
class cmd_domain_auth_policy(SuperCommand):
"""Manage authentication policies on the domain."""
subcommands = {
"list": cmd_domain_auth_policy_list(),
"view": cmd_domain_auth_policy_view(),
"create": cmd_domain_auth_policy_create(),
"modify": cmd_domain_auth_policy_modify(),
"delete": cmd_domain_auth_policy_delete(),
}