/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <ldap.h>
#include <stdlib.h>
#include <netdb.h>
#include <pthread.h>
#include <unistd.h>
#include <resolv.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <assert.h>
#include <note.h>
#include <errno.h>
#include <cryptoutil.h>
#include <smbsrv/libsmbns.h>
#include <smbns_dyndns.h>
#include <smbns_krb.h>
/*
* domainControllerFunctionality
*
* This rootDSE attribute indicates the functional level of the DC.
*/
#define SMB_ADS_DCLEVEL_W2K 0
/*
* msDs-supportedEncryptionTypes (Windows Server 2008 only)
*
* This attribute defines the encryption types supported by the system.
* Encryption Types:
* - DES cbc mode with CRC-32
* - DES cbc mode with RSA-MD5
* - AES-128
* - AES-256
*/
};
};
/*
* UserAccountControl flags: manipulate user account properties.
*
* The hexadecimal value of the following property flags are based on MSDN
* article # 305144.
*/
/*
* Length of "dc=" prefix.
*/
static char *smb_ads_computer_objcls[] = {
"top", "person", "organizationalPerson",
};
static char *smb_ads_share_objcls[] = {
};
/* Cached ADS server to communicate with */
/*
* SMB ADS config cache is maintained to facilitate the detection of
* changes in configuration that is relevant to AD selection.
*/
typedef struct smb_ads_config {
typedef struct smb_ads_avpair {
char *avp_attr;
char *avp_val;
/* query status */
typedef enum smb_ads_qstat {
typedef struct smb_ads_host_list {
int ah_cnt;
static int smb_ads_open_main(smb_ads_handle_t **, char *, char *, char *);
static int smb_ads_add_computer(smb_ads_handle_t *, int, char *);
static int smb_ads_modify_computer(smb_ads_handle_t *, int, char *);
static int smb_ads_computer_op(smb_ads_handle_t *, int, int, char *);
smb_ads_avpair_t *, int, char *);
static int smb_ads_update_computer_cntrl_attr(smb_ads_handle_t *, int, char *);
static void smb_ads_free_cached_host(void);
static int smb_ads_alloc_attr(LDAPMod **, int);
static void smb_ads_free_attr(LDAPMod **);
static int smb_ads_get_dc_level(smb_ads_handle_t *);
smb_ads_avpair_t *);
smb_ads_avpair_t *);
static boolean_t smb_ads_is_same_domain(char *, char *);
static char *smb_ads_get_sharedn(const char *, const char *, const char *);
static krb5_enctype *smb_ads_get_enctypes(int, int *);
/*
* smb_ads_init
*
* Initializes the ADS config cache.
*/
void
smb_ads_init(void)
{
(void) smb_config_getstr(SMB_CI_ADS_SITE,
/* Force -lads to load, for dtrace. */
}
void
smb_ads_fini(void)
{
}
/*
* smb_ads_refresh
*
* (See smbd_join.c)
*
* Clearing the smb_ads_cached_host_info would allow the next DC
* discovery process to pick up an AD based on the new AD configuration.
*/
void
{
if (force_rediscovery) {
(void) _DsForceRediscovery(NULL, 0);
}
}
/*
* smb_ads_build_unc_name
*
* Construct the UNC name of the share object in the format of
* \\hostname.domain\shareUNC
*
* Returns 0 on success, -1 on error.
*/
int
{
return (-1);
return (0);
}
/*
* The cached ADS host is no longer valid if one of the following criteria
* is satisfied:
*
* 1) not in the specified domain
* 2) not the sought host (if specified)
* 3) not reachable
*
* The caller is responsible for acquiring the smb_ads_cached_host_mtx lock
* prior to calling this function.
*
* Return B_TRUE if the cache host is still valid. Otherwise, return B_FALSE.
*/
static boolean_t
{
if (!smb_ads_cached_host_info)
return (B_FALSE);
return (B_FALSE);
return (B_TRUE);
}
/*
* smb_ads_match_hosts_same_domain
*
* Returns true, if the cached ADS host is in the same domain as the
* current (given) domain.
*/
static boolean_t
{
char *cached_host_domain;
return (B_FALSE);
if (cached_host_domain == NULL)
return (B_FALSE);
return (B_FALSE);
return (B_TRUE);
}
/*
* smb_ads_dup_host_info
*
* Duplicates the passed smb_ads_host_info_t structure.
* Caller must free memory allocated by this method.
*
* Returns a reference to the duplicated smb_ads_host_info_t structure.
* Returns NULL on error.
*/
static smb_ads_host_info_t *
{
return (NULL);
return (dup_host);
}
/*
* smb_ads_find_host
*
* Finds an ADS host in a given domain.
*
* If the cached host is valid, it will be used. Otherwise, a DC will
* be selected based on the following criteria:
*
* 1) pdc (aka preferred DC) configuration
* 2) AD site configuration - the scope of the DNS lookup will be
* restricted to the specified site.
* 3) DC on the same subnet
*
* The above items are listed in decreasing preference order. The selected
* DC must be online.
*
* If this function is called during domain join, the specified kpasswd server
* takes precedence over preferred DC, AD site, and so on.
*
* Parameters:
* domain: fully-qualified domain name.
*
* Returns:
* A copy of the cached host info is returned. The caller is responsible
* for deallocating the memory returned by this function.
*/
/*ARGSUSED*/
{
int tries;
(void) mutex_lock(&smb_ads_cached_host_mtx);
if (smb_ads_validate_cache_host(domain)) {
(void) mutex_unlock(&smb_ads_cached_host_mtx);
return (host);
}
(void) mutex_unlock(&smb_ads_cached_host_mtx);
/*
* The _real_ DC Locator is over in idmapd.
* Door call over there to get it.
*/
tries = 15;
NULL, /* ComputerName */
NULL, /* DomainGuid */
NULL, /* SiteName */
&dci);
switch (status) {
case 0:
break;
/*
* We can see these errors when joining a domain, if we race
* asking idmap for the DC before it knows the new domain.
*/
case NT_STATUS_NO_SUCH_DOMAIN: /* Specified domain unknown */
case NT_STATUS_INVALID_SERVER_STATE: /* not in domain mode. */
if (--tries > 0) {
(void) sleep(1);
goto again;
}
/* FALLTHROUGH */
case NT_STATUS_CANT_WAIT: /* timeout over in idmap */
default:
return (NULL);
}
goto out;
case AF_INET: {
sizeof (in_addr_t));
break;
}
case AF_INET6: {
sizeof (in6_addr_t));
break;
}
default:
goto out;
}
(void) mutex_lock(&smb_ads_cached_host_mtx);
if (!smb_ads_cached_host_info)
(void) mutex_unlock(&smb_ads_cached_host_mtx);
out:
return (host);
}
/*
* Return the number of dots in a string.
*/
static int
smb_ads_count_dots(const char *s)
{
int ndots = 0;
while (*s) {
if (*s++ == '.')
ndots++;
}
return (ndots);
}
/*
* Convert a domain name in dot notation to distinguished name format,
* for example: sun.com -> dc=sun,dc=com.
*
* Returns a pointer to an allocated buffer containing the distinguished
* name.
*/
static char *
{
const char *s;
char *dn_name;
int ndots;
int len;
return (NULL);
++ndots;
return (NULL);
s = domain_name;
while (*s) {
if (*s == '.') {
} else {
buf[0] = *s;
}
++s;
}
return (dn_name);
}
/*
* smb_ads_free_cached_host
*
* Free the memory use by the global smb_ads_cached_host_info & set it to NULL.
*/
static void
smb_ads_free_cached_host(void)
{
(void) mutex_lock(&smb_ads_cached_host_mtx);
if (smb_ads_cached_host_info) {
}
(void) mutex_unlock(&smb_ads_cached_host_mtx);
}
/*
* smb_ads_open
* Open a LDAP connection to an ADS server if the system is in domain mode.
* Acquire both Kerberos TGT and LDAP service tickets for the host principal.
*
* This function should only be called after the system is successfully joined
* to a domain.
*/
smb_ads_open(void)
{
smb_ads_handle_t *h;
if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
return (NULL);
return (NULL);
if (err != 0) {
return (NULL);
}
return (h);
}
static int
{
return (LDAP_PARAM_ERROR);
interact++) {
}
return (LDAP_SUCCESS);
}
/*
* smb_ads_open_main
* Open a LDAP connection to an ADS server.
* If ADS is enabled and the administrative username, password, and
* ADS domain are defined then query DNS to find an ADS server if this is the
* very first call to this routine. After an ADS server is found then this
* server will be used everytime this routine is called until the system is
* rebooted or the ADS server becomes unavailable then an ADS server will
* be queried again. After the connection is made then an ADS handle
* is created to be returned.
*
* After the LDAP connection, the LDAP version will be set to 3 using
* ldap_set_option().
*
* The LDAP connection is bound before the ADS handle is returned.
* Parameters:
* domain - fully-qualified domain name
* user - the user account for whom the Kerberos TGT ticket and ADS
* service tickets are acquired.
* password - password of the specified user
*
* Returns:
* NULL : can't connect to ADS server or other errors
* smb_ads_handle_t* : handle to ADS server
*/
static int
char *password)
{
if (err != 0)
return (err);
}
return (SMB_ADS_CANT_LOCATE_DC);
return (ENOMEM);
}
return (SMB_ADS_LDAP_INIT);
}
!= LDAP_SUCCESS) {
(void) ldap_unbind(ld);
return (SMB_ADS_LDAP_SETOPT);
}
return (SMB_ADS_LDAP_SETOPT);
}
/*
* ah->domain is often used for generating service principal name.
* Convert it to lower case for RFC 4120 section 6.2.1 conformance.
*/
return (SMB_ADS_LDAP_SET_DOM);
}
return (ENOMEM);
}
return (ENOMEM);
}
} else {
}
if (rc != LDAP_SUCCESS) {
return (SMB_ADS_LDAP_SASL_BIND);
}
return (SMB_ADS_SUCCESS);
}
/*
* smb_ads_close
* Close connection to ADS server and free memory allocated for ADS handle.
* LDAP unbind is called here.
* Parameters:
* ah: handle to ADS server
* Returns:
* void
*/
void
{
return;
/* close and free connection resources */
}
/*
* smb_ads_alloc_attr
*
* Since the attrs is a null-terminated array, all elements
* in the array (except the last one) will point to allocated
* memory.
*/
static int
{
int i;
for (i = 0; i < (num - 1); i++) {
return (-1);
}
}
return (0);
}
/*
* smb_ads_free_attr
* Free memory allocated when publishing a share.
* Parameters:
* attrs: an array of LDAPMod pointers
* Returns:
* None
*/
static void
{
int i;
for (i = 0; attrs[i]; i++) {
}
}
/*
* Returns share DN in an allocated buffer. The format of the DN is
* cn=<sharename>,<container RDNs>,<domain DN>
*
* If the domain DN is not included in the container parameter,
* then it will be appended to create the share DN.
*
* The caller must free the allocated buffer.
*/
static char *
const char *domain_dn)
{
char *share_dn;
if (container_len >= domain_len) {
/* offset to last domain_len characters */
domain_dn, domain_len) == 0)
}
if (append_domain)
else
}
/*
* smb_ads_add_share
* Call by smb_ads_publish_share to create share object in ADS.
* This routine specifies the attributes of an ADS LDAP share object. The first
* attribute and values define the type of ADS object, the share object. The
* second attribute and value define the UNC of the share data for the share
* object. The LDAP synchronous add command is used to add the object into ADS.
* The container location to add the object needs to specified.
* Parameters:
* ah : handle to ADS server
* adsShareName: name of share object to be created in ADS
* shareUNC : share name on NetForce
* adsContainer: location in ADS to create share object
*
* Returns:
* -1 : error
* 0 : success
*/
int
const char *unc_name, const char *adsContainer)
{
int j = 0;
char *share_dn;
int ret;
return (-1);
return (-1);
}
if (ret == LDAP_NO_SUCH_OBJECT) {
" AD. Container does not exist: %s.\n",
} else {
}
return (ret);
}
return (0);
}
/*
* smb_ads_del_share
* Call by smb_ads_remove_share to remove share object from ADS. The container
* location to remove the object needs to specified. The LDAP synchronous
* delete command is used.
* Parameters:
* ah : handle to ADS server
* adsShareName: name of share object in ADS to be removed
* adsContainer: location of share object in ADS
* Returns:
* -1 : error
* 0 : success
*/
static int
const char *adsContainer)
{
char *share_dn;
int ret;
return (-1);
return (-1);
}
return (0);
}
/*
* smb_ads_escape_search_filter_chars
*
* This routine will escape the special characters found in a string
* that will later be passed to the ldap search filter.
*
* RFC 1960 - A String Representation of LDAP Search Filters
* 3. String Search Filter Definition
* If a value must contain one of the characters '*' OR '(' OR ')',
* these characters
* should be escaped by preceding them with the backslash '\' character.
*
* RFC 2252 - LDAP Attribute Syntax Definitions
* a backslash quoting mechanism is used to escape
* the following separator symbol character (such as "'", "$" or "#") if
* it should occur in that string.
*/
static int
{
return (-1);
while (*src) {
if (!avail) {
*dst = 0;
return (-1);
}
switch (*src) {
case '\\':
case '\'':
case '$':
case '#':
case '*':
case '(':
case ')':
*dst++ = '\\';
avail--;
/* fall through */
default:
avail--;
}
}
*dst = 0;
return (0);
}
/*
* smb_ads_lookup_share
* The search filter is set to search for a specific share name in the
* specified ADS container. The LDSAP synchronous search command is used.
* Parameters:
* ah : handle to ADS server
* adsShareName: name of share object in ADS to be searched
* adsContainer: location of share object in ADS
* Returns:
* -1 : error
* 0 : not found
* 1 : found
*/
int
const char *adsContainer, char *unc_name)
{
char *share_dn;
int ret;
return (-1);
return (-1);
attrs[0] = "cn";
return (-1);
}
"(&(objectClass=volume)(uNCName=%s))", tmpbuf);
if (ret != LDAP_NO_SUCH_OBJECT)
(void) ldap_msgfree(res);
return (0);
}
/* no match is found */
(void) ldap_msgfree(res);
return (0);
}
/* free the search results */
(void) ldap_msgfree(res);
return (1);
}
/*
* smb_ads_publish_share
* Publish share into ADS. If a share name already exist in ADS in the same
* container then the existing share object is removed before adding the new
* share object.
* Parameters:
* ah : handle return from smb_ads_open
* adsShareName: name of share to be added to ADS directory
* shareUNC : name of share on client, can be NULL to use the same name
* as adsShareName
* adsContainer: location for share to be added in ADS directory, ie
* ou=share_folder
* uncType : use UNC_HOSTNAME to use hostname for UNC, use UNC_HOSTADDR
* to use host ip addr for UNC.
* Returns:
* -1 : error
* 0 : success
*/
int
{
int ret;
return (-1);
return (-1);
switch (ret) {
case 1:
break;
case 0:
if (ret == LDAP_ALREADY_EXISTS)
ret = -1;
break;
case -1:
default:
/* return with error code */
ret = -1;
}
return (ret);
}
/*
* smb_ads_remove_share
* Remove share from ADS. A search is done first before explicitly removing
* the share.
* Parameters:
* ah : handle return from smb_ads_open
* adsShareName: name of share to be removed from ADS directory
* adsContainer: location for share to be removed from ADS directory, ie
* ou=share_folder
* Returns:
* -1 : error
* 0 : success
*/
int
{
int ret;
return (-1);
return (-1);
if (ret == 0)
return (0);
if (ret == -1)
return (-1);
}
/*
* smb_ads_get_default_comp_container_dn
*
* Build the distinguished name for the default computer conatiner (i.e. the
* pre-defined Computers container).
*/
static void
{
}
/*
* smb_ads_get_default_comp_dn
*
* Build the distinguished name for this system.
*/
static void
{
}
/*
* smb_ads_add_computer
*
* Returns 0 upon success. Otherwise, returns -1.
*/
static int
{
}
/*
* smb_ads_modify_computer
*
* Returns 0 upon success. Otherwise, returns -1.
*/
static int
{
}
/*
* smb_ads_get_dc_level
*
* Returns the functional level of the DC upon success.
* Otherwise, -1 is returned.
*/
static int
{
char **vals;
attr[0] = SMB_ADS_ATTR_DCLEVEL;
0, &res) != LDAP_SUCCESS) {
(void) ldap_msgfree(res);
return (-1);
}
/* no match for the specified attribute is found */
(void) ldap_msgfree(res);
return (-1);
}
if (entry) {
SMB_ADS_ATTR_DCLEVEL)) == NULL) {
/*
* Observed the values aren't populated
* by the Windows 2000 server.
*/
(void) ldap_msgfree(res);
return (SMB_ADS_DCLEVEL_W2K);
}
}
(void) ldap_msgfree(res);
return (rc);
}
/*
* The fully-qualified hostname returned by this function is often used for
* constructing service principal name. Return the fully-qualified hostname
* in lower case for RFC 4120 section 6.2.1 conformance.
*/
static int
{
return (-1);
return (0);
}
static int
{
int j = -1;
int max;
return (-1);
return (-1);
/* The SPN attribute is multi-valued and must be 1 or greater */
return (-1);
/* The UPN attribute is single-valued and cannot be zero */
return (-1);
}
return (-1);
}
/* objectClass attribute is not modifiable. */
if (op == LDAP_MOD_ADD) {
}
sam_val[1] = 0;
ctl_val[0] = usrctl_buf;
ctl_val[1] = 0;
fqh_val[1] = 0;
/* enctypes support starting in Windows Server 2008 */
if (dclevel > SMB_ADS_DCLEVEL_W2K3) {
encrypt_val[0] = encrypt_buf;
encrypt_val[1] = 0;
}
switch (op) {
case LDAP_MOD_ADD:
ret = -1;
}
break;
case LDAP_MOD_REPLACE:
ret = -1;
}
break;
default:
ret = -1;
}
return (ret);
}
/*
* Delete an ADS computer account.
*/
static void
{
int rc;
}
/*
* Gets the value of the given attribute.
*/
static smb_ads_qstat_t
{
char **vals;
if (!vals)
return (SMB_ADS_STAT_NOT_FOUND);
if (!vals[0]) {
return (SMB_ADS_STAT_NOT_FOUND);
}
return (rc);
}
/*
* Process query's result.
*/
static smb_ads_qstat_t
{
return (SMB_ADS_STAT_ERR);
return (SMB_ADS_STAT_NOT_FOUND);
return (SMB_ADS_STAT_ERR);
switch (rc) {
case SMB_ADS_STAT_FOUND:
/*
* Returns SMB_ADS_STAT_DUP to avoid overwriting
* the computer account of another system whose
* NetBIOS name collides with that of the current
* system.
*/
break;
case SMB_ADS_STAT_NOT_FOUND:
/*
* Pre-created computer account doesn't have
* the dNSHostname attribute. It's been observed
* that the dNSHostname attribute is only set after
* a successful domain join.
* Returns SMB_ADS_STAT_FOUND as the account is
* pre-created for the current system.
*/
break;
default:
break;
}
if (rc != SMB_ADS_STAT_FOUND)
return (rc);
if (avpair)
return (rc);
}
/*
* smb_ads_lookup_computer_n_attr
*
* If avpair is NULL, checks the status of the specified computer account.
* Otherwise, looks up the value of the specified computer account's attribute.
* If found, the value field of the avpair will be allocated and set. The
* caller should free the allocated buffer.
*
* Return:
* SMB_ADS_STAT_FOUND - if both the computer and the specified attribute is
* found.
* SMB_ADS_STAT_NOT_FOUND - if either the computer or the specified attribute
* is not found.
* SMB_ADS_STAT_DUP - if the computer account is already used by other systems
* in the AD. This could happen if the hostname of multiple
* systems resolved to the same NetBIOS name.
* SMB_ADS_STAT_ERR - any failure.
*/
static smb_ads_qstat_t
{
return (SMB_ADS_STAT_ERR);
attrs[0] = SMB_ADS_ATTR_DNSHOST;
if (avpair) {
return (SMB_ADS_STAT_ERR);
}
return (SMB_ADS_STAT_ERR);
"(&(objectClass=computer)(%s=%s))", SMB_ADS_ATTR_SAMACCT,
&res) != LDAP_SUCCESS) {
(void) ldap_msgfree(res);
return (SMB_ADS_STAT_NOT_FOUND);
}
/* free the search results */
(void) ldap_msgfree(res);
return (rc);
}
/*
* 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.
*/
static smb_ads_qstat_t
{
dn);
if (stat == SMB_ADS_STAT_NOT_FOUND) {
}
if (stat == SMB_ADS_STAT_FOUND) {
}
return (stat);
}
/*
* smb_ads_update_computer_cntrl_attr
*
* Modify the user account control attribute of an existing computer
* object on AD.
*
* Returns LDAP error code.
*/
static int
{
int ret = 0;
return (LDAP_NO_MEMORY);
ctl_val[0] = usrctl_buf;
ctl_val[1] = 0;
}
return (ret);
}
/*
* smb_ads_lookup_computer_attr_kvno
*
* Lookup the value of the Kerberos version number attribute of the computer
* account.
*/
static krb5_kvno
{
}
return (kvno);
}
/*
* smb_ads_join
*
* Besides the NT-4 style domain join (using MS-RPC), CIFS server also
* provides the domain join using Kerberos Authentication, Keberos
* Change & Set password, and LDAP protocols. Basically, AD join
* operation would require the following tickets to be acquired for the
* the user account that is provided for the domain join.
*
* 1) a Keberos TGT ticket,
* 2) a ldap service ticket, and
*
* The ADS client first sends a ldap search request to find out whether
* or not the workstation trust account already exists in the Active Directory.
* The existing computer object for this workstation will be removed and
* a new one will be added. The machine account password is randomly
* generated and set for the newly created computer object using KPASSWD
* protocol (See RFC 3244). Once the password is set, our ADS client
* finalizes the machine account by modifying the user acount control
* attribute of the computer object. Kerberos keys derived from the machine
* account password will be stored locally in /etc/krb5/krb5.keytab file.
* That would be needed while acquiring Kerberos TGT ticket for the host
* principal after the domain join operation.
*/
{
int cnt, x;
if (rc != 0) {
return (rc);
}
return (SMB_ADJOIN_ERR_GET_DCLEVEL);
}
switch (qstat) {
case SMB_ADS_STAT_FOUND:
return (SMB_ADJOIN_ERR_MOD_TRUST_ACCT);
}
break;
case SMB_ADS_STAT_NOT_FOUND:
return (SMB_ADJOIN_ERR_ADD_TRUST_ACCT);
}
break;
default:
if (qstat == SMB_ADS_STAT_DUP)
else
return (rc);
}
if (smb_krb5_ctx_init(&ctx) != 0) {
goto adjoin_cleanup;
}
goto adjoin_cleanup;
}
!= 0) {
goto adjoin_cleanup;
}
/* New machine_passwd was filled in by our caller. */
goto adjoin_cleanup;
}
/*
* Only members of Domain Admins and Enterprise Admins can set
* the TRUSTED_FOR_DELEGATION userAccountControl flag.
* Try to set this, but don't fail the join if we can't.
* Look into just removing this...
*/
usrctl_flags = (
if (x != LDAP_SUCCESS && (usrctl_flags &
"TRUSTED_FOR_DELEGATION userAccountControl flag on the "
"machine account in Active Directory. It may be necessary "
"to set that via Active Directory administration.");
usrctl_flags &=
goto set_ctl_again;
}
if (x != LDAP_SUCCESS) {
goto adjoin_cleanup;
}
goto adjoin_cleanup;
}
goto adjoin_cleanup;
}
if (rc != SMB_ADJOIN_ERR_INIT_KRB_CTX) {
if (rc != SMB_ADJOIN_ERR_GET_SPNS)
}
/* commit keytab file */
if (rc == SMB_ADS_SUCCESS) {
}
} else {
}
return (rc);
}
struct xlate_table {
int err;
const char const *msg;
};
static const struct xlate_table
adjoin_table[] = {
{ SMB_ADS_SUCCESS, "Success" },
"Failed creating a Kerberos context." },
"Failed to resolve default credential cache." },
"Failed parsing the user principal name." },
"Failed getting initial credentials. (Wrong password?)" },
"Failed initializing the credential cache." },
"Failed to update the credential cache." },
"Failed to locate a domain controller." },
"Failed to create an LDAP handle." },
"Failed to set an LDAP option." },
"Failed to set the LDAP handle DN." },
"Failed to bind the LDAP handle. "
"Usually indicates an authentication problem." },
"Failed to generate machine password." },
{ SMB_ADJOIN_ERR_GET_DCLEVEL, "Unknown functional level of "
"the domain controller. The rootDSE attribute named "
"\"domainControllerFunctionality\" is missing from the "
"Active Directory." },
{ SMB_ADJOIN_ERR_ADD_TRUST_ACCT, "Failed to create the "
"workstation trust account." },
{ SMB_ADJOIN_ERR_MOD_TRUST_ACCT, "Failed to modify the "
"workstation trust account." },
{ SMB_ADJOIN_ERR_DUP_TRUST_ACCT, "Failed to create the "
"workstation trust account because its name is already "
"in use." },
{ SMB_ADJOIN_ERR_TRUST_ACCT, "Error in querying the "
"workstation trust account" },
{ SMB_ADJOIN_ERR_INIT_KRB_CTX, "Failed to initialize Kerberos "
"context." },
{ SMB_ADJOIN_ERR_GET_SPNS, "Failed to get Kerberos "
"principals." },
{ SMB_ADJOIN_ERR_KSETPWD, "Failed to set machine password." },
{ SMB_ADJOIN_ERR_UPDATE_CNTRL_ATTR, "Failed to modify "
"userAccountControl attribute of the workstation trust "
"account." },
{ SMB_ADJOIN_ERR_WRITE_KEYTAB, "Error in writing to local "
"keytab file (i.e /etc/krb5/krb5.keytab)." },
{ SMB_ADJOIN_ERR_IDMAP_SET_DOMAIN, "Failed to update idmap "
"configuration." },
{ SMB_ADJOIN_ERR_IDMAP_REFRESH, "Failed to refresh idmap "
"service." },
{ SMB_ADJOIN_ERR_COMMIT_KEYTAB, "Failed to commit changes to "
"local keytab file (i.e. /etc/krb5/krb5.keytab)." },
"Failed to authenticate using the new computer account." },
"Failed to store computer account information locally." },
{ 0, NULL }
};
/*
* smb_ads_strerror
*
* Lookup an error message for the specific adjoin error code.
*/
const char *
{
return ("Unknown error code.");
}
void
{
const char *s = smb_ads_strerror(err);
}
/*
* smb_ads_lookup_msdcs
*
* If server argument is set, try to locate the specified DC.
* If it is set to empty string, locate any DCs in the specified domain.
* Returns the discovered DC via buf.
*
* fqdn - fully-qualified domain name
* dci - the name and address of the found DC
*/
{
return (NT_STATUS_INTERNAL_ERROR);
ipstr[0] = '\0';
return (NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND);
return (NT_STATUS_SUCCESS);
}
static krb5_enctype *
{
if (dclevel >= SMB_ADS_DCLEVEL_W2K8) {
} else {
}
return (encptr);
}