diff options
Diffstat (limited to 'usr/src/cmd')
| -rw-r--r-- | usr/src/cmd/idmap/idmapd/idmap_config.c | 16 | ||||
| -rw-r--r-- | usr/src/cmd/idmap/idmapd/idmap_config.h | 3 | ||||
| -rw-r--r-- | usr/src/cmd/idmap/idmapd/init.c | 17 | ||||
| -rw-r--r-- | usr/src/cmd/smbsrv/smbadm/smbadm.c | 142 | ||||
| -rw-r--r-- | usr/src/cmd/smbsrv/smbd/smbd_join.c | 242 | ||||
| -rw-r--r-- | usr/src/cmd/zfs/zfs_main.c | 15 |
6 files changed, 172 insertions, 263 deletions
diff --git a/usr/src/cmd/idmap/idmapd/idmap_config.c b/usr/src/cmd/idmap/idmapd/idmap_config.c index 02ae8029cf..b8c2867489 100644 --- a/usr/src/cmd/idmap/idmapd/idmap_config.c +++ b/usr/src/cmd/idmap/idmapd/idmap_config.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ @@ -1455,6 +1455,11 @@ idmap_cfg_load_smf(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg, if (rc != 0) (*errors)++; + rc = get_val_bool(handles, "use_ads", + &pgcfg->use_ads, B_TRUE); + if (rc != 0) + (*errors)++; + rc = get_val_bool(handles, "use_lsa", &pgcfg->use_lsa, B_TRUE); if (rc != 0) @@ -1797,6 +1802,12 @@ idmap_cfg_discover(idmap_cfg_handles_t *handles, idmap_pg_config_t *pgcfg) { ad_disc_t ad_ctx = handles->ad_ctx; + if (pgcfg->use_ads == B_FALSE) { + if (DBG(CONFIG, 1)) + idmapdlog(LOG_DEBUG, "ADS disabled."); + return; + } + if (DBG(CONFIG, 1)) idmapdlog(LOG_DEBUG, "Running discovery."); @@ -1916,6 +1927,9 @@ idmap_cfg_load(idmap_cfg_t *cfg, int flags) changed += update_bool(&live_pgcfg->eph_map_unres_sids, &new_pgcfg.eph_map_unres_sids, "unresolvable_sid_mapping"); + changed += update_bool(&live_pgcfg->use_ads, + &new_pgcfg.use_ads, "use_ads"); + changed += update_bool(&live_pgcfg->use_lsa, &new_pgcfg.use_lsa, "use_lsa"); diff --git a/usr/src/cmd/idmap/idmapd/idmap_config.h b/usr/src/cmd/idmap/idmapd/idmap_config.h index 66e5431031..31ae7b6ad1 100644 --- a/usr/src/cmd/idmap/idmapd/idmap_config.h +++ b/usr/src/cmd/idmap/idmapd/idmap_config.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ #ifndef _IDMAP_CONFIG_H @@ -108,6 +108,7 @@ typedef struct idmap_pg_config { char *nldap_winname_attr; int directory_based_mapping; /* enum */ boolean_t eph_map_unres_sids; + boolean_t use_ads; boolean_t use_lsa; boolean_t disable_cross_forest_trusts; } idmap_pg_config_t; diff --git a/usr/src/cmd/idmap/idmapd/init.c b/usr/src/cmd/idmap/idmapd/init.c index 43c18b6293..3e5dde7ad8 100644 --- a/usr/src/cmd/idmap/idmapd/init.c +++ b/usr/src/cmd/idmap/idmapd/init.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013 Nexenta Systems, Inc. All rights reserved. */ /* @@ -119,8 +120,12 @@ reload_gcs() int num_trustfor = pgcfg->num_trusted_forests; ad_disc_domainsinforest_t *domain_in_forest; - if (pgcfg->domain_name == NULL) { - /* No domain name specified - workgroup mode. */ + if (pgcfg->use_ads == B_FALSE || + pgcfg->domain_name == NULL) { + /* + * ADS disabled, or no domain name specified. + * Not using adutils. (but still can use lsa) + */ new_gcs = NULL; new_num_gcs = 0; goto out; @@ -248,8 +253,12 @@ reload_dcs(void) int old_num_dcs = _idmapdstate.num_dcs; idmap_pg_config_t *pgcfg = &_idmapdstate.cfg->pgcfg; - if (pgcfg->domain_name == NULL) { - /* No domain name specified - workgroup mode. */ + if (pgcfg->use_ads == B_FALSE || + pgcfg->domain_name == NULL) { + /* + * ADS disabled, or no domain name specified. + * Not using adutils. (but still can use lsa) + */ new_dcs = NULL; new_num_dcs = 0; goto out; diff --git a/usr/src/cmd/smbsrv/smbadm/smbadm.c b/usr/src/cmd/smbsrv/smbadm/smbadm.c index 7874a71bed..07887fa7a3 100644 --- a/usr/src/cmd/smbsrv/smbadm/smbadm.c +++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c @@ -19,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ /* @@ -229,8 +229,14 @@ smbadm_cmdusage(FILE *fp, smbadm_cmdinfo_t *cmd) return; case HELP_JOIN: +#if 0 /* Don't document "-p" yet, still needs work (NX 11960) */ + (void) fprintf(fp, gettext("\t%s -p domain\n" + "\t%s -u username domain\n\t%s -w workgroup\n"), + cmd->name, cmd->name, cmd->name); +#else (void) fprintf(fp, gettext("\t%s -u username domain\n" "\t%s -w workgroup\n"), cmd->name, cmd->name); +#endif return; case HELP_LIST: @@ -457,45 +463,25 @@ smbadm_join(int argc, char **argv) uint32_t mode = 0; char option; - while ((option = getopt(argc, argv, "u:w:")) != -1) { + while ((option = getopt(argc, argv, "pu:w")) != -1) { + if (mode != 0) { + (void) fprintf(stderr, gettext( + "join options are mutually exclusive\n")); + smbadm_usage(B_FALSE); + } switch (option) { - case 'w': - if (mode != 0) { - (void) fprintf(stderr, - gettext("-u and -w must only appear " - "once and are mutually exclusive\n")); - smbadm_usage(B_FALSE); - } - - mode = SMB_SECMODE_WORKGRP; - domain = optarg; + case 'p': + mode = SMB_SECMODE_DOMAIN; + /* leave username = NULL */ break; case 'u': - if (mode != 0) { - (void) fprintf(stderr, - gettext("-u and -w must only appear " - "once and are mutually exclusive\n")); - smbadm_usage(B_FALSE); - } - mode = SMB_SECMODE_DOMAIN; username = optarg; + break; - if ((domain = argv[optind]) == NULL) { - /* - * The domain was not specified as a separate - * argument, check for the combination forms. - */ - (void) strlcpy(buf, username, sizeof (buf)); - smbadm_extract_domain(buf, &username, &domain); - } - - if ((username == NULL) || (*username == '\0')) { - (void) fprintf(stderr, - gettext("missing username\n")); - smbadm_usage(B_FALSE); - } + case 'w': + mode = SMB_SECMODE_WORKGRP; break; default: @@ -504,16 +490,28 @@ smbadm_join(int argc, char **argv) } } + if (optind < argc) + domain = argv[optind]; + + if (username != NULL && domain == NULL) { + /* + * The domain was not specified as a separate + * argument, check for the combination forms. + */ + (void) strlcpy(buf, username, sizeof (buf)); + smbadm_extract_domain(buf, &username, &domain); + } + if ((domain == NULL) || (*domain == '\0')) { (void) fprintf(stderr, gettext("missing %s name\n"), (mode == SMB_SECMODE_WORKGRP) ? "workgroup" : "domain"); smbadm_usage(B_FALSE); } - if (mode == SMB_SECMODE_WORKGRP) + if (mode == SMB_SECMODE_WORKGRP) { return (smbadm_join_workgroup(domain)); - else - return (smbadm_join_domain(domain, username)); + } + return (smbadm_join_domain(domain, username)); } /* @@ -582,37 +580,46 @@ smbadm_join_domain(const char *domain, const char *username) if (!smbadm_join_prompt(jdi.domain_name)) return (0); - if ((p = strchr(username, '+')) != NULL) { - ++p; - - len = (int)(p - username); - if (len > sizeof (jdi.domain_name)) - len = sizeof (jdi.domain_name); - - (void) strlcpy(jdi.domain_username, username, len); - (void) strlcpy(jdi.domain_passwd, p, - sizeof (jdi.domain_passwd)); - } else { - (void) strlcpy(jdi.domain_username, username, - sizeof (jdi.domain_username)); - } + /* + * Note: username is null for "unsecure join" + * (join using a pre-created computer account) + * No password either. + */ + if (username != NULL) { + if ((p = strchr(username, '+')) != NULL) { + ++p; - if (smb_name_validate_account(jdi.domain_username) != ERROR_SUCCESS) { - (void) fprintf(stderr, - gettext("username contains invalid characters\n")); - smbadm_usage(B_FALSE); - } + len = (int)(p - username); + if (len > sizeof (jdi.domain_name)) + len = sizeof (jdi.domain_name); - if (*jdi.domain_passwd == '\0') { - prompt = gettext("Enter domain password: "); + (void) strlcpy(jdi.domain_username, username, len); + (void) strlcpy(jdi.domain_passwd, p, + sizeof (jdi.domain_passwd)); + } else { + (void) strlcpy(jdi.domain_username, username, + sizeof (jdi.domain_username)); + } - if ((p = getpassphrase(prompt)) == NULL) { - (void) fprintf(stderr, gettext("missing password\n")); + if (smb_name_validate_account(jdi.domain_username) + != ERROR_SUCCESS) { + (void) fprintf(stderr, + gettext("username contains invalid characters\n")); smbadm_usage(B_FALSE); } - (void) strlcpy(jdi.domain_passwd, p, - sizeof (jdi.domain_passwd)); + if (*jdi.domain_passwd == '\0') { + prompt = gettext("Enter domain password: "); + + if ((p = getpassphrase(prompt)) == NULL) { + (void) fprintf(stderr, gettext( + "missing password\n")); + smbadm_usage(B_FALSE); + } + + (void) strlcpy(jdi.domain_passwd, p, + sizeof (jdi.domain_passwd)); + } } (void) printf(gettext("Joining %s ... this may take a minute ...\n"), @@ -635,6 +642,19 @@ smbadm_join_domain(const char *domain, const char *username) bzero(&jdi, sizeof (jdi)); return (1); + case NT_STATUS_BAD_NETWORK_PATH: + (void) fprintf(stderr, + gettext("failed to resolve domain controller name\n")); + bzero(&jdi, sizeof (jdi)); + return (1); + + case NT_STATUS_NETWORK_ACCESS_DENIED: + case NT_STATUS_BAD_NETWORK_NAME: + (void) fprintf(stderr, + gettext("failed connecting to domain controller\n")); + bzero(&jdi, sizeof (jdi)); + return (1); + default: (void) fprintf(stderr, gettext("failed to join %s: %s\n"), jdi.domain_name, xlate_nt_status(status)); diff --git a/usr/src/cmd/smbsrv/smbd/smbd_join.c b/usr/src/cmd/smbsrv/smbd/smbd_join.c index 54fcaccfbb..74d5fac9be 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_join.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ #include <syslog.h> @@ -48,8 +49,7 @@ static cond_t smbd_dc_cv; static void *smbd_dc_monitor(void *); static void smbd_dc_update(void); -static boolean_t smbd_set_netlogon_cred(void); -static int smbd_get_kpasswd_srv(char *, size_t); +/* Todo: static boolean_t smbd_set_netlogon_cred(void); */ static uint32_t smbd_join_workgroup(smb_joininfo_t *); static uint32_t smbd_join_domain(smb_joininfo_t *); @@ -164,8 +164,8 @@ smbd_dc_update(void) { char domain[MAXHOSTNAMELEN]; smb_domainex_t info; - smb_domain_t *primary; - + smb_domain_t *di; + DWORD status; if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) { (void) smb_getdomainname(domain, MAXHOSTNAMELEN); @@ -175,26 +175,24 @@ smbd_dc_update(void) if (!smb_locate_dc(domain, "", &info)) { smb_log(smbd.s_loghd, LOG_NOTICE, "smbd_dc_update: %s: locate failed", domain); - } else { - primary = &info.d_primary; + return; + } - smb_config_setdomaininfo(primary->di_nbname, - primary->di_fqname, - primary->di_sid, - primary->di_u.di_dns.ddi_forest, - primary->di_u.di_dns.ddi_guid); + di = &info.d_primary; + smb_log(smbd.s_loghd, LOG_NOTICE, + "smbd_dc_update: %s: located %s", domain, info.d_dc); - smb_log(smbd.s_loghd, LOG_NOTICE, - "smbd_dc_update: %s: located %s", domain, info.d_dc); - } + status = mlsvc_netlogon(info.d_dc, di->di_nbname); + if (status != NT_STATUS_SUCCESS) { + syslog(LOG_NOTICE, + "failed to establish NETLOGON credential chain"); - if (smbd_set_netlogon_cred()) { /* * Restart required because the domain changed * or the credential chain setup failed. */ smb_log(smbd.s_loghd, LOG_NOTICE, - "smbd_dc_update: %s: smb/server restart required"); + "smbd_dc_update: smb/server restart required"); if (smb_smf_restart_service() != 0) smb_log(smbd.s_loghd, LOG_ERR, @@ -225,148 +223,6 @@ smbd_join(smb_joininfo_t *info) return (status); } -/* - * smbd_set_netlogon_cred - * - * If the system is joined to an AD domain via kclient, SMB daemon will need - * to establish the NETLOGON credential chain. - * - * Since the kclient has updated the machine password stored in SMF - * repository, the cached ipc_info must be updated accordingly by calling - * smb_ipc_commit. - * - * Due to potential replication delays in a multiple DC environment, the - * NETLOGON rpc request must be sent to the DC, to which the KPASSWD request - * is sent. If the DC discovered by the SMB daemon is different than the - * kpasswd server, the current connection with the DC will be torn down - * and a DC discovery process will be triggered to locate the kpasswd - * server. - * - * If joining a new domain, the domain_name property must be set after a - * successful credential chain setup. - */ -static boolean_t -smbd_set_netlogon_cred(void) -{ - char kpasswd_srv[MAXHOSTNAMELEN]; - char kpasswd_domain[MAXHOSTNAMELEN]; - char sam_acct[SMB_SAMACCT_MAXLEN]; - char ipc_usr[SMB_USERNAME_MAXLEN]; - char *dom; - boolean_t new_domain = B_FALSE; - smb_domainex_t dxi; - smb_domain_t *di; - - if (smb_match_netlogon_seqnum()) - return (B_FALSE); - - (void) smb_config_getstr(SMB_CI_KPASSWD_SRV, kpasswd_srv, - sizeof (kpasswd_srv)); - - if (*kpasswd_srv == '\0') - return (B_FALSE); - - /* - * If the domain join initiated by smbadm join CLI is in - * progress, don't do anything. - */ - (void) smb_getsamaccount(sam_acct, sizeof (sam_acct)); - smb_ipc_get_user(ipc_usr, SMB_USERNAME_MAXLEN); - if (smb_strcasecmp(ipc_usr, sam_acct, 0)) - return (B_FALSE); - - di = &dxi.d_primary; - if (!smb_domain_getinfo(&dxi)) - (void) smb_getfqdomainname(di->di_fqname, MAXHOSTNAMELEN); - - (void) smb_config_getstr(SMB_CI_KPASSWD_DOMAIN, kpasswd_domain, - sizeof (kpasswd_domain)); - - if (*kpasswd_domain != '\0' && - smb_strcasecmp(kpasswd_domain, di->di_fqname, 0)) { - dom = kpasswd_domain; - new_domain = B_TRUE; - } else { - dom = di->di_fqname; - } - - /* - * DC discovery will be triggered if the domain info is not - * currently cached or the SMB daemon has previously discovered a DC - * that is different than the kpasswd server. - */ - if (new_domain || smb_strcasecmp(dxi.d_dc, kpasswd_srv, 0) != 0) { - if (*dxi.d_dc != '\0') - mlsvc_disconnect(dxi.d_dc); - - if (!smb_locate_dc(dom, kpasswd_srv, &dxi)) { - if (!smb_locate_dc(di->di_fqname, "", &dxi)) { - smb_ipc_commit(); - return (B_FALSE); - } - } - } - - smb_ipc_commit(); - if (mlsvc_netlogon(dxi.d_dc, di->di_nbname)) { - syslog(LOG_NOTICE, - "failed to establish NETLOGON credential chain"); - return (B_TRUE); - } else { - if (new_domain) { - smb_config_setdomaininfo(di->di_nbname, di->di_fqname, - di->di_sid, - di->di_u.di_dns.ddi_forest, - di->di_u.di_dns.ddi_guid); - (void) smb_config_setstr(SMB_CI_KPASSWD_DOMAIN, ""); - } - } - - return (new_domain); -} - -/* - * Retrieve the kpasswd server from krb5.conf. - * - * Initialization of the locate dc thread. - * Returns 0 on success, an error number if thread creation fails. - */ -static int -smbd_get_kpasswd_srv(char *srv, size_t len) -{ - FILE *fp; - static char buf[512]; - char *p; - - *srv = '\0'; - p = getenv("KRB5_CONFIG"); - if (p == NULL || *p == '\0') - p = "/etc/krb5/krb5.conf"; - - if ((fp = fopen(p, "r")) == NULL) - return (-1); - - while (fgets(buf, sizeof (buf), fp)) { - - /* Weed out any comment text */ - (void) trim_whitespace(buf); - if (*buf == '#') - continue; - - if ((p = strstr(buf, "kpasswd_server")) != NULL) { - if ((p = strchr(p, '=')) != NULL) { - (void) trim_whitespace(++p); - (void) strlcpy(srv, p, len); - } - break; - } - } - - - (void) fclose(fp); - return ((*srv == '\0') ? -1 : 0); -} - static uint32_t smbd_join_workgroup(smb_joininfo_t *info) { @@ -387,11 +243,10 @@ smbd_join_workgroup(smb_joininfo_t *info) static uint32_t smbd_join_domain(smb_joininfo_t *info) { - uint32_t status; - unsigned char passwd_hash[SMBAUTH_HASH_SZ]; - char dc[MAXHOSTNAMELEN]; + static unsigned char zero_hash[SMBAUTH_HASH_SZ]; smb_domainex_t dxi; smb_domain_t *di; + uint32_t status; /* * Ensure that any previous membership of this domain has @@ -399,43 +254,50 @@ smbd_join_domain(smb_joininfo_t *info) * will ensure that we don't attempt a NETLOGON_SAMLOGON * when attempting to find the PDC. */ - (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_FALSE); - if (smb_auth_ntlm_hash(info->domain_passwd, passwd_hash) - != SMBAUTH_SUCCESS) { - syslog(LOG_ERR, "smbd: could not compute ntlm hash for '%s'", - info->domain_username); - return (NT_STATUS_INTERNAL_ERROR); - } + /* Clear DNS local (ADS) lookup cache too. */ + smb_ads_refresh(); - smb_ipc_set(info->domain_username, passwd_hash); + /* + * Use a NULL session while searching for a DC, and + * while getting information about the domain. + */ + smb_ipc_set(MLSVC_ANON_USER, zero_hash); + + if (!smb_locate_dc(info->domain_name, "", &dxi)) { + syslog(LOG_ERR, "smbd: failed locating " + "domain controller for %s", + info->domain_name); + status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + goto errout; + } - (void) smbd_get_kpasswd_srv(dc, sizeof (dc)); /* info->domain_name could either be NetBIOS domain name or FQDN */ - if (smb_locate_dc(info->domain_name, dc, &dxi)) { - status = mlsvc_join(&dxi, info->domain_username, - info->domain_passwd); - - if (status == NT_STATUS_SUCCESS) { - di = &dxi.d_primary; - smbd_set_secmode(SMB_SECMODE_DOMAIN); - smb_config_setdomaininfo(di->di_nbname, di->di_fqname, - di->di_sid, - di->di_u.di_dns.ddi_forest, - di->di_u.di_dns.ddi_guid); - smb_ipc_commit(); - return (status); - } - - smb_ipc_rollback(); + status = mlsvc_join(&dxi, info->domain_username, info->domain_passwd); + if (status != NT_STATUS_SUCCESS) { syslog(LOG_ERR, "smbd: failed joining %s (%s)", info->domain_name, xlate_nt_status(status)); - return (status); + goto errout; } + /* + * Success! + * + * Strange, mlsvc_join does some of the work to + * save the config, then the rest happens here. + * Todo: Do the config update all in one place. + */ + di = &dxi.d_primary; + smbd_set_secmode(SMB_SECMODE_DOMAIN); + smb_config_setdomaininfo(di->di_nbname, di->di_fqname, + di->di_sid, + di->di_u.di_dns.ddi_forest, + di->di_u.di_dns.ddi_guid); + smb_ipc_commit(); + return (status); + +errout: smb_ipc_rollback(); - syslog(LOG_ERR, "smbd: failed locating domain controller for %s", - info->domain_name); - return (NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND); + return (status); } diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c index 4228f5c50a..a2828db3e9 100644 --- a/usr/src/cmd/zfs/zfs_main.c +++ b/usr/src/cmd/zfs/zfs_main.c @@ -63,6 +63,7 @@ #include <libuutil.h> #include <aclutils.h> #include <directory.h> +#include <idmap.h> #include "zfs_iter.h" #include "zfs_util.h" @@ -2439,9 +2440,8 @@ userspace_cb(void *arg, const char *domain, uid_t rid, uint64_t space) /* SMB */ char sid[ZFS_MAXNAMELEN + 32]; uid_t id; - uint64_t classes; int err; - directory_error_t e; + int flag = IDMAP_REQ_FLG_USE_CACHE; smbentity = B_TRUE; @@ -2458,10 +2458,13 @@ userspace_cb(void *arg, const char *domain, uid_t rid, uint64_t space) if (err == 0) { rid = id; if (!cb->cb_sid2posix) { - e = directory_name_from_sid(NULL, sid, &name, - &classes); - if (e != NULL) - directory_error_free(e); + if (type == USTYPE_SMB_USR) { + (void) idmap_getwinnamebyuid(rid, flag, + &name, NULL); + } else { + (void) idmap_getwinnamebygid(rid, flag, + &name, NULL); + } if (name == NULL) name = sid; } |
