diff options
Diffstat (limited to 'usr/src/lib/smbsrv')
-rw-r--r-- | usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c | 22 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmb/common/libsmb.h | 3 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c | 10 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmbns/common/libsmbns.h | 2 | ||||
-rw-r--r-- | usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c | 147 |
5 files changed, 97 insertions, 87 deletions
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c index 9191cfbce6..00326cb7dc 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c @@ -100,11 +100,22 @@ mlsvc_join(smb_joininfo_t *info, smb_joinres_t *res) char addrbuf[INET6_ADDRSTRLEN]; smb_domainex_t dxi; smb_domain_t *di = &dxi.d_primary; + char *container; + char *username; DWORD status; int rc; bzero(&dxi, sizeof (dxi)); + if (info->container_name[0] != '\0') + container = info->container_name; + else + container = NULL; + if (info->domain_username[0] != '\0') + username = info->domain_username; + else + username = NULL; + /* * Domain join support: AD (Kerberos+LDAP) or MS-RPC? */ @@ -125,11 +136,10 @@ mlsvc_join(smb_joininfo_t *info, smb_joinres_t *res) */ (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_FALSE); - if (info->domain_username[0] != '\0') { + if (username != NULL) { (void) smb_auth_ntlm_hash(info->domain_passwd, passwd_hash); - smb_ipc_set(info->domain_username, passwd_hash); - syslog(LOG_INFO, "smbd: joining with user %s", - info->domain_username); + smb_ipc_set(username, passwd_hash); + syslog(LOG_INFO, "smbd: joining with user %s", username); } else { smb_ipc_set(MLSVC_ANON_USER, zero_hash); syslog(LOG_INFO, "smbd: joining with anonymous"); @@ -210,14 +220,14 @@ mlsvc_join(smb_joininfo_t *info, smb_joinres_t *res) * Create or update our machine account on the DC. * A non-null user means we do "secure join". */ - if (info->domain_username[0] != '\0') { + if (username != NULL) { /* * If enabled, try to join using AD Services. */ status = NT_STATUS_UNSUCCESSFUL; if (ads_enabled) { syslog(LOG_INFO, "use_ads=true (LDAP join)"); - res->join_err = smb_ads_join(di->di_fqname, + res->join_err = smb_ads_join(di->di_fqname, container, info->domain_username, info->domain_passwd, machine_pw); if (res->join_err == SMB_ADS_SUCCESS) { diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 48336f2d73..388553e03c 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -241,10 +241,11 @@ extern void smb_update_netlogon_seqnum(void); /* See also: smb_joininfo_xdr() */ typedef struct smb_joininfo { + uint32_t mode; char domain_name[MAXHOSTNAMELEN]; + char container_name[MAXHOSTNAMELEN]; char domain_username[SMB_USERNAME_MAXLEN + 1]; char domain_passwd[SMB_PASSWD_MAXLEN + 1]; - uint32_t mode; } smb_joininfo_t; /* See also: smb_joinres_xdr() */ diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c index 96702e4c7d..23d10f9dbf 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c @@ -207,10 +207,17 @@ smb_get_dcinfo(char *namebuf, uint32_t namebuflen, smb_inaddr_t *ipaddr) bool_t smb_joininfo_xdr(XDR *xdrs, smb_joininfo_t *objp) { + if (!xdr_uint32_t(xdrs, &objp->mode)) + return (FALSE); + if (!xdr_vector(xdrs, (char *)objp->domain_name, MAXHOSTNAMELEN, sizeof (char), (xdrproc_t)xdr_char)) return (FALSE); + if (!xdr_vector(xdrs, (char *)objp->container_name, MAXHOSTNAMELEN, + sizeof (char), (xdrproc_t)xdr_char)) + return (FALSE); + if (!xdr_vector(xdrs, (char *)objp->domain_username, SMB_USERNAME_MAXLEN + 1, sizeof (char), (xdrproc_t)xdr_char)) return (FALSE); @@ -219,9 +226,6 @@ smb_joininfo_xdr(XDR *xdrs, smb_joininfo_t *objp) SMB_PASSWD_MAXLEN + 1, sizeof (char), (xdrproc_t)xdr_char)) return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->mode)) - return (FALSE); - return (TRUE); } diff --git a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h index fc8bd69957..7cde269335 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h +++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h @@ -106,7 +106,7 @@ extern int smb_ads_lookup_share(smb_ads_handle_t *, const char *, const char *, char *); extern int smb_ads_add_share(smb_ads_handle_t *, const char *, const char *, const char *); -extern smb_ads_status_t smb_ads_join(char *, char *, char *, char *); +extern smb_ads_status_t smb_ads_join(char *, char *, char *, char *, char *); extern void smb_ads_log_errmsg(smb_ads_status_t); extern const char *smb_ads_strerror(int); extern uint32_t smb_ads_lookup_msdcs(char *, smb_dcinfo_t *); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c index ca2897aea1..8bbe0e8afb 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c @@ -1187,33 +1187,22 @@ smb_ads_remove_share(smb_ads_handle_t *ah, const char *adsShareName, } /* - * smb_ads_get_default_comp_container_dn + * smb_ads_get_new_comp_dn * - * Build the distinguished name for the default computer conatiner (i.e. the - * pre-defined Computers container). + * Build the distinguished name for a new machine account + * prepend: cn=SamAccountName, cn=Computers, ...domain_dn... */ static void -smb_ads_get_default_comp_container_dn(smb_ads_handle_t *ah, char *buf, - size_t buflen) -{ - (void) snprintf(buf, buflen, "cn=%s,%s", SMB_ADS_COMPUTERS_CN, - ah->domain_dn); -} - -/* - * smb_ads_get_default_comp_dn - * - * Build the distinguished name for this system. - */ -static void -smb_ads_get_default_comp_dn(smb_ads_handle_t *ah, char *buf, size_t buflen) +smb_ads_get_new_comp_dn(smb_ads_handle_t *ah, char *buf, size_t buflen, + char *container) { char nbname[NETBIOS_NAME_SZ]; - char container_dn[SMB_ADS_DN_MAX]; + if (container == NULL) + container = "cn=" SMB_ADS_COMPUTERS_CN; (void) smb_getnetbiosname(nbname, sizeof (nbname)); - smb_ads_get_default_comp_container_dn(ah, container_dn, SMB_ADS_DN_MAX); - (void) snprintf(buf, buflen, "cn=%s,%s", nbname, container_dn); + (void) snprintf(buf, buflen, "cn=%s,%s,%s", + nbname, container, ah->domain_dn); } /* @@ -1495,19 +1484,17 @@ smb_ads_getattr(LDAP *ld, LDAPMessage *entry, smb_ads_avpair_t *avpair) * machine account, the DNS name will be not set, and that's OK. * If we see a DNS name and it doesn't match our DNS name, we'll * assume the account belongs to someone else and return "DUP". + * + * Only do the DNS name check for our initial search for the + * machine account, which has avpair->avp_attr = SMB_ADS_ATTR_DN */ static smb_ads_qstat_t smb_ads_get_qstat(smb_ads_handle_t *ah, LDAPMessage *res, smb_ads_avpair_t *avpair) { - char fqhost[MAXHOSTNAMELEN]; - smb_ads_avpair_t dnshost_avp; smb_ads_qstat_t rc = SMB_ADS_STAT_FOUND; LDAPMessage *entry; - if (smb_ads_getfqhostname(ah, fqhost, MAXHOSTNAMELEN)) - return (SMB_ADS_STAT_ERR); - if (ldap_count_entries(ah->ld, res) == 0) { syslog(LOG_DEBUG, "smbns: find_computer, " "ldap_count_entries zero"); @@ -1520,48 +1507,62 @@ smb_ads_get_qstat(smb_ads_handle_t *ah, LDAPMessage *res, return (SMB_ADS_STAT_ERR); } - syslog(LOG_DEBUG, "smbns: find_computer, check DNS name"); - dnshost_avp.avp_attr = SMB_ADS_ATTR_DNSHOST; - rc = smb_ads_getattr(ah->ld, entry, &dnshost_avp); + /* Have an LDAP entry (found something) */ + syslog(LOG_DEBUG, "smbns: find_computer, have LDAP resp."); - /* - * Check the status of finding the DNS name - */ - switch (rc) { - case SMB_ADS_STAT_FOUND: - /* - * Found a DNS name. If it doesn't match ours, - * returns SMB_ADS_STAT_DUP to avoid overwriting - * the computer account of another system whose - * NetBIOS name collides with that of the current - * system. - */ - if (strcasecmp(dnshost_avp.avp_val, fqhost)) { - syslog(LOG_DEBUG, "smbns: find_computer, " - "duplicate name (%s)", - dnshost_avp.avp_val); - rc = SMB_ADS_STAT_DUP; - } - free(dnshost_avp.avp_val); - break; + if (avpair != NULL && + strcmp(avpair->avp_attr, SMB_ADS_ATTR_DN) == 0) { + char fqhost[MAXHOSTNAMELEN]; + smb_ads_avpair_t dnshost_avp; + + syslog(LOG_DEBUG, "smbns: find_computer, check DNS name"); + + if (smb_ads_getfqhostname(ah, fqhost, MAXHOSTNAMELEN)) + return (SMB_ADS_STAT_ERR); + + dnshost_avp.avp_attr = SMB_ADS_ATTR_DNSHOST; + dnshost_avp.avp_val = NULL; + rc = smb_ads_getattr(ah->ld, entry, &dnshost_avp); - case SMB_ADS_STAT_NOT_FOUND: /* - * No dNSHostname attribute, so probably a - * pre-created computer account. Use it. - * - * Returns SMB_ADS_STAT_FOUND for the status - * of finding the machine account. + * Status from finding the DNS name value */ - rc = SMB_ADS_STAT_FOUND; - break; + switch (rc) { + case SMB_ADS_STAT_FOUND: + /* + * Found a DNS name. If it doesn't match ours, + * returns SMB_ADS_STAT_DUP to avoid overwriting + * the computer account of another system whose + * NetBIOS name collides with that of the current + * system. + */ + if (strcasecmp(dnshost_avp.avp_val, fqhost)) { + syslog(LOG_DEBUG, "smbns: find_computer, " + "duplicate name (%s)", + dnshost_avp.avp_val); + rc = SMB_ADS_STAT_DUP; + } + free(dnshost_avp.avp_val); + break; + + case SMB_ADS_STAT_NOT_FOUND: + /* + * No dNSHostname attribute, so probably a + * pre-created computer account. Use it. + * + * Returns SMB_ADS_STAT_FOUND for the status + * of finding the machine account. + */ + rc = SMB_ADS_STAT_FOUND; + break; - default: - break; - } + default: + break; + } - if (rc != SMB_ADS_STAT_FOUND) - return (rc); + if (rc != SMB_ADS_STAT_FOUND) + return (rc); + } if (avpair) { syslog(LOG_DEBUG, "smbns: find_computer, check %s", @@ -1661,10 +1662,9 @@ smb_ads_lookup_computer_n_attr(smb_ads_handle_t *ah, smb_ads_avpair_t *avpair, /* * smb_ads_find_computer * - * Starts by searching for the system's AD computer object in the default - * container (i.e. cn=Computers). If not found, searches the entire directory. - * If found, 'dn' will be set to the distinguished name of the system's AD - * computer object. + * Searches the directory for the machine account (SamAccountName) + * If found, 'dn' will be set to the distinguished name of the system's + * AD computer object. */ static smb_ads_qstat_t smb_ads_find_computer(smb_ads_handle_t *ah, char *dn) @@ -1675,15 +1675,9 @@ smb_ads_find_computer(smb_ads_handle_t *ah, char *dn) avpair.avp_attr = SMB_ADS_ATTR_DN; avpair.avp_val = NULL; - smb_ads_get_default_comp_container_dn(ah, dn, SMB_ADS_DN_MAX); - stat = smb_ads_lookup_computer_n_attr(ah, &avpair, LDAP_SCOPE_ONELEVEL, - dn); - - if (stat == SMB_ADS_STAT_NOT_FOUND) { - (void) strlcpy(dn, ah->domain_dn, SMB_ADS_DN_MAX); - stat = smb_ads_lookup_computer_n_attr(ah, &avpair, - LDAP_SCOPE_SUBTREE, dn); - } + (void) strlcpy(dn, ah->domain_dn, SMB_ADS_DN_MAX); + stat = smb_ads_lookup_computer_n_attr(ah, &avpair, + LDAP_SCOPE_SUBTREE, dn); if (stat == SMB_ADS_STAT_FOUND) { (void) strlcpy(dn, avpair.avp_val, SMB_ADS_DN_MAX); @@ -1776,7 +1770,8 @@ smb_ads_lookup_computer_attr_kvno(smb_ads_handle_t *ah, char *dn) * principal after the domain join operation. */ smb_ads_status_t -smb_ads_join(char *domain, char *user, char *usr_passwd, char *machine_passwd) +smb_ads_join(char *domain, char *container, + char *user, char *usr_passwd, char *machine_passwd) { smb_ads_handle_t *ah = NULL; krb5_context ctx = NULL; @@ -1822,7 +1817,7 @@ smb_ads_join(char *domain, char *user, char *usr_passwd, char *machine_passwd) case SMB_ADS_STAT_NOT_FOUND: new_acct = B_TRUE; - smb_ads_get_default_comp_dn(ah, dn, SMB_ADS_DN_MAX); + smb_ads_get_new_comp_dn(ah, dn, SMB_ADS_DN_MAX, container); syslog(LOG_INFO, "smb_ads_join: machine account not found." " Creating: %s", dn); if (smb_ads_add_computer(ah, dclevel, dn) != 0) { |