diff options
| -rw-r--r-- | source3/Doxyfile | 8 | ||||
| -rw-r--r-- | source3/Makefile.in | 3 | ||||
| -rw-r--r-- | source3/client/client.c | 21 | ||||
| -rw-r--r-- | source3/include/ads.h | 7 | ||||
| -rw-r--r-- | source3/lib/charcnv.c | 4 | ||||
| -rw-r--r-- | source3/lib/util_seaccess.c | 2 | ||||
| -rw-r--r-- | source3/lib/util_sid.c | 31 | ||||
| -rw-r--r-- | source3/lib/util_str.c | 4 | ||||
| -rw-r--r-- | source3/libads/ads_status.c | 6 | ||||
| -rw-r--r-- | source3/libads/ads_struct.c | 1 | ||||
| -rw-r--r-- | source3/libads/ads_utils.c | 20 | ||||
| -rw-r--r-- | source3/libads/disp_sec.c | 3 | ||||
| -rw-r--r-- | source3/libads/krb5_setpw.c | 31 | ||||
| -rw-r--r-- | source3/libads/ldap.c | 202 | ||||
| -rw-r--r-- | source3/libads/sasl.c | 4 | ||||
| -rw-r--r-- | source3/nsswitch/winbindd_ads.c | 197 | ||||
| -rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 4 | ||||
| -rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 10 | ||||
| -rw-r--r-- | source3/utils/net_rpc_samsync.c | 44 | 
19 files changed, 291 insertions, 311 deletions
diff --git a/source3/Doxyfile b/source3/Doxyfile index fe71065c24..bbdc5da7e7 100644 --- a/source3/Doxyfile +++ b/source3/Doxyfile @@ -124,7 +124,7 @@ MAN_LINKS              = NO  #---------------------------------------------------------------------------  GENERATE_XML           = NO  #--------------------------------------------------------------------------- -# Configuration options related to the preprocessor    +# configuration options related to the preprocessor     #---------------------------------------------------------------------------  ENABLE_PREPROCESSING   = NO  MACRO_EXPANSION        = NO @@ -136,14 +136,14 @@ PREDEFINED             =  EXPAND_AS_DEFINED      =   SKIP_FUNCTION_MACROS   = YES  #--------------------------------------------------------------------------- -# Configuration::addtions related to external references    +# configuration::additions related to external references     #---------------------------------------------------------------------------  TAGFILES               =   GENERATE_TAGFILE       =   ALLEXTERNALS           = NO  PERL_PATH              = /usr/bin/perl  #--------------------------------------------------------------------------- -# Configuration options related to the dot tool    +# configuration options related to the dot tool     #---------------------------------------------------------------------------  HAVE_DOT               = YES  CLASS_GRAPH            = YES @@ -159,7 +159,7 @@ MAX_DOT_GRAPH_HEIGHT   = 1024  GENERATE_LEGEND        = YES  DOT_CLEANUP            = YES  #--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine    +# configuration::additions related to the search engine     #---------------------------------------------------------------------------  SEARCHENGINE           = NO  CGI_NAME               = search.cgi diff --git a/source3/Makefile.in b/source3/Makefile.in index bd09ee55c8..32c2e3f70f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -154,7 +154,8 @@ PARAM_OBJ = param/loadparm.o param/params.o dynconfig.o  LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \  	     libads/krb5_setpw.o libads/kerberos.o libads/ldap_user.o \  	     libads/ads_struct.o libads/ads_status.o \ -             libads/disp_sec.o libads/ads_utils.o +             libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \ +	     libads/ads_ldap.o  LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o diff --git a/source3/client/client.c b/source3/client/client.c index eb6b572760..f25ed1623b 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -2436,9 +2436,24 @@ static struct cli_state *do_connect(const char *server, const char *share)  	if (!cli_send_tconX(c, sharename, "?????",  			    password, strlen(password)+1)) { -		d_printf("tree connect failed: %s\n", cli_errstr(c)); -		cli_shutdown(c); -		return NULL; +		pstring full_share; + +		/* +		 * Some servers require \\server\share for the share +		 * while others are happy with share as we gave above +		 * Lets see if we give it the long form if it works +		 */ +		pstrcpy(full_share, "\\\\"); +		pstrcat(full_share, server); +		pstrcat(full_share, "\\"); +		pstrcat(full_share, sharename); +		if (!cli_send_tconX(c, full_share, "?????", password, +					strlen(password) + 1)) { + +			d_printf("tree connect failed: %s\n", cli_errstr(c)); +			cli_shutdown(c); +			return NULL; +		}  	}  	DEBUG(4,(" tconx ok\n")); diff --git a/source3/include/ads.h b/source3/include/ads.h index 0181ae535e..88a90229b1 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -15,6 +15,7 @@ typedef struct {  		char *realm;  		char *workgroup;  		char *ldap_server; +		char *ldap_uri;  		int foreign; /* set to 1 if connecting to a foreign realm */  	} server; @@ -255,5 +256,7 @@ typedef void **ADS_MODLIST;  /* ads auth control flags */ -#define ADS_AUTH_DISABLE_KERBEROS 1 -#define ADS_AUTH_NO_BIND 2 +#define ADS_AUTH_DISABLE_KERBEROS 0x01 +#define ADS_AUTH_NO_BIND          0x02 +#define ADS_AUTH_ANON_BIND        0x04 +#define ADS_AUTH_SIMPLE_BIND      0x08 diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index cd8aa4fe55..d0cef52c92 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -522,12 +522,12 @@ int push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)   *   * @retval The number of bytes occupied by the string in the destination   **/ -int push_utf8_allocate(void **dest, const char *src) +int push_utf8_allocate(char **dest, const char *src)  {  	int src_len = strlen(src)+1;  	*dest = NULL; -	return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, dest);	 +	return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest);	  }  /**************************************************************************** diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index b137023e55..456d7ba9e2 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -226,7 +226,7 @@ void se_map_standard(uint32 *access_mask, struct standard_mapping *mapping)   "Access-Checking" document in MSDN.  *****************************************************************************/  -BOOL se_access_check(SEC_DESC *sd, const NT_USER_TOKEN *token, +BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token,  		     uint32 acc_desired, uint32 *acc_granted,   		     NTSTATUS *status)  { diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index e9635fc7f8..1439471f64 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -34,6 +34,7 @@ DOM_SID global_sid_World_Domain;	    	/* Everyone domain */  DOM_SID global_sid_World;    				/* Everyone */  DOM_SID global_sid_Creator_Owner_Domain;    /* Creator Owner domain */  DOM_SID global_sid_NT_Authority;    		/* NT Authority */ +DOM_SID global_sid_System;    		/* System */  DOM_SID global_sid_NULL;            		/* NULL sid */  DOM_SID global_sid_Authenticated_Users;		/* All authenticated rids */  DOM_SID global_sid_Network;					/* Network rids */ @@ -58,6 +59,12 @@ NT_USER_TOKEN anonymous_token = {      anon_sid_array  }; +static DOM_SID system_sid_array[4]; +NT_USER_TOKEN system_token = { +    1, +    system_sid_array +}; +  /****************************************************************************   Lookup string names for SID types.  ****************************************************************************/ @@ -101,6 +108,10 @@ const char *sid_type_lookup(uint32 sid_type)  void generate_wellknown_sids(void)  { +	static BOOL initialised = False; +	if (initialised)  +		return; +  	string_to_sid(&global_sid_Builtin, "S-1-5-32");  	string_to_sid(&global_sid_Builtin_Administrators, "S-1-5-32-544");  	string_to_sid(&global_sid_Builtin_Users, "S-1-5-32-545"); @@ -111,6 +122,7 @@ void generate_wellknown_sids(void)  	string_to_sid(&global_sid_Creator_Owner, "S-1-3-0");  	string_to_sid(&global_sid_Creator_Group, "S-1-3-1");  	string_to_sid(&global_sid_NT_Authority, "S-1-5"); +	string_to_sid(&global_sid_System, "S-1-5-18");  	string_to_sid(&global_sid_NULL, "S-1-0-0");  	string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11");  	string_to_sid(&global_sid_Network, "S-1-5-2"); @@ -120,6 +132,17 @@ void generate_wellknown_sids(void)  	sid_copy( &anonymous_token.user_sids[0], &global_sid_World);  	sid_copy( &anonymous_token.user_sids[1], &global_sid_Network);  	sid_copy( &anonymous_token.user_sids[2], &global_sid_Anonymous); + +	/* Create the system token. */ +	sid_copy( &system_token.user_sids[0], &global_sid_System); +	 +	initialised = True; +} + +NT_USER_TOKEN *get_system_token(void)  +{ +	generate_wellknown_sids(); /* The token is initialised here */ +	return &system_token;  }  /************************************************************************** @@ -347,7 +370,7 @@ void sid_copy(DOM_SID *dst, const DOM_SID *src)  /*****************************************************************   Write a sid out into on-the-wire format.  *****************************************************************/   -BOOL sid_linearize(char *outbuf, size_t len, DOM_SID *sid) +BOOL sid_linearize(char *outbuf, size_t len, const DOM_SID *sid)  {  	size_t i; @@ -366,7 +389,7 @@ BOOL sid_linearize(char *outbuf, size_t len, DOM_SID *sid)  /*****************************************************************   parse a on-the-wire SID to a DOM_SID  *****************************************************************/   -BOOL sid_parse(char *inbuf, size_t len, DOM_SID *sid) +BOOL sid_parse(const char *inbuf, size_t len, DOM_SID *sid)  {  	int i;  	if (len < 8) return False; @@ -482,7 +505,7 @@ BOOL sid_check_is_in_builtin(const DOM_SID *sid)   Calculates size of a sid.  *****************************************************************/   -size_t sid_size(DOM_SID *sid) +size_t sid_size(const DOM_SID *sid)  {  	if (sid == NULL)  		return 0; @@ -518,7 +541,7 @@ BOOL non_mappable_sid(DOM_SID *sid)    return the binary string representation of a DOM_SID    caller must free  */ -char *sid_binstring(DOM_SID *sid) +char *sid_binstring(const DOM_SID *sid)  {  	char *buf, *s;  	int len = sid_size(sid); diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 1b38db2c94..75338de4d3 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -468,7 +468,7 @@ char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, si  	for(i = 0; i < len; i++) {  		int val = (src[i] & 0xff); -		if(isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val)) +		if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))  			dest[i] = src[i];  		else  			dest[i] = '_'; @@ -501,7 +501,7 @@ char *StrnCpy(char *dest,const char *src,size_t n)  like strncpy but copies up to the character marker.  always null terminates.  returns a pointer to the character marker in the source string (src).  ****************************************************************************/ -char *strncpyn(char *dest, const char *src,size_t n, char c) +char *strncpyn(char *dest, const char *src, size_t n, char c)  {  	char *p;  	size_t str_len; diff --git a/source3/libads/ads_status.c b/source3/libads/ads_status.c index d85f9c9b58..80fdb99eac 100644 --- a/source3/libads/ads_status.c +++ b/source3/libads/ads_status.c @@ -72,6 +72,12 @@ NTSTATUS ads_ntstatus(ADS_STATUS status)  	if (status.error_type == ADS_ERROR_NT){  		return status.err.nt_status;	  	} +#ifdef HAVE_LDAP +	if ((status.error_type == ADS_ERROR_LDAP)  +	    && (status.err.rc == LDAP_NO_MEMORY)) { +		return NT_STATUS_NO_MEMORY; +	} +#endif  	if (ADS_ERR_OK(status)) return NT_STATUS_OK;  	return NT_STATUS_UNSUCCESSFUL;  } diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index b68c822ce3..3cdd015bf4 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -122,6 +122,7 @@ void ads_destroy(ADS_STRUCT **ads)  		SAFE_FREE((*ads)->server.realm);  		SAFE_FREE((*ads)->server.workgroup);  		SAFE_FREE((*ads)->server.ldap_server); +		SAFE_FREE((*ads)->server.ldap_uri);  		SAFE_FREE((*ads)->auth.realm);  		SAFE_FREE((*ads)->auth.password); diff --git a/source3/libads/ads_utils.c b/source3/libads/ads_utils.c index fc8a270021..626c177926 100644 --- a/source3/libads/ads_utils.c +++ b/source3/libads/ads_utils.c @@ -3,7 +3,8 @@     ads (active directory) utility library     Copyright (C) Stefan (metze) Metzmacher 2002 -    +   Copyright (C) Andrew Tridgell 2001 +       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 2 of the License, or @@ -21,9 +22,6 @@  #include "includes.h" -#ifdef HAVE_ADS - -  /*   translated the ACB_CTRL Flags to UserFlags (userAccountControl)   */  @@ -168,4 +166,16 @@ uint32 ads_gtype2atype(uint32 gtype)  	return atype;  } -#endif +/* turn a sAMAccountType into a SID_NAME_USE */ +enum SID_NAME_USE ads_atype_map(uint32 atype) +{ +	switch (atype & 0xF0000000) { +	case ATYPE_GLOBAL_GROUP: +		return SID_NAME_DOM_GRP; +	case ATYPE_ACCOUNT: +		return SID_NAME_USER; +	default: +		DEBUG(1,("hmm, need to map account type 0x%x\n", atype)); +	} +	return SID_NAME_UNKNOWN; +} diff --git a/source3/libads/disp_sec.c b/source3/libads/disp_sec.c index a930fd6fe0..a7b0bf6f07 100644 --- a/source3/libads/disp_sec.c +++ b/source3/libads/disp_sec.c @@ -20,8 +20,6 @@  #include "includes.h" -#ifdef HAVE_ADS -  static struct perm_mask_str {  	uint32  mask;  	char   *str; @@ -158,5 +156,4 @@ void ads_disp_sd(SEC_DESC *sd)  	printf("-------------- End Of Security Descriptor\n");  } -#endif diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index a49b6cbe3b..8079c0953f 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -471,4 +471,35 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,  } +/** + * Set the machine account password + * @param ads connection to ads server + * @param hostname machine whose password is being set + * @param password new password + * @return status of password change + **/ +ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads, +				    const char *hostname,  +				    const char *password) +{ +	ADS_STATUS status; +	char *host = strdup(hostname); +	char *principal;  + +	strlower(host); + +	/* +	  we need to use the '$' form of the name here, as otherwise the +	  server might end up setting the password for a user instead +	 */ +	asprintf(&principal, "%s$@%s", host, ads->auth.realm); +	 +	status = krb5_set_password(ads->auth.kdc_server, principal, password, ads->auth.time_offset); +	 +	free(host); +	free(principal); + +	return status; +} +  #endif diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 7a0afb1a81..2133bf0719 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -22,7 +22,7 @@  #include "includes.h" -#ifdef HAVE_ADS +#ifdef HAVE_LDAP  /**   * @file ldap.c @@ -67,6 +67,29 @@ static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)  	return True;  } +/* +  try a connection to a given ldap server, based on URL, returning True if successful + */ +static BOOL ads_try_connect_uri(ADS_STRUCT *ads) +{ +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) +	DEBUG(5,("ads_try_connect: trying ldap server at URI '%s'\n",  +		 ads->server.ldap_uri)); + +	 +	if (ldap_initialize((LDAP**)&(ads->ld), ads->server.ldap_uri) == LDAP_SUCCESS) { +		return True; +	} +	DEBUG(0, ("ldap_initialize: %s\n", strerror(errno))); +	 +#else  + +	DEBUG(1, ("no URL support in LDAP libs!\n")); +#endif + +	return False; +} +  /* used by the IP comparison function */  struct ldap_ip {  	struct in_addr ip; @@ -210,6 +233,13 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)  	ads->last_attempt = time(NULL);  	ads->ld = NULL; +	/* try with a URL based server */ + +	if (ads->server.ldap_uri && +	    ads_try_connect_uri(ads)) { +		goto got_connection; +	} +  	/* try with a user specified server */  	if (ads->server.ldap_server &&   	    ads_try_connect(ads, ads->server.ldap_server, LDAP_PORT)) { @@ -278,6 +308,14 @@ got_connection:  		return ADS_SUCCESS;  	} +	if (ads->auth.flags & ADS_AUTH_ANON_BIND) { +		return ADS_ERROR(ldap_simple_bind_s( ads->ld, NULL, NULL)); +	} + +	if (ads->auth.flags & ADS_AUTH_SIMPLE_BIND) { +		return ADS_ERROR(ldap_simple_bind_s( ads->ld, ads->auth.user_name, ads->auth.password)); +	} +  	return ads_sasl_bind(ads);  } @@ -741,7 +779,11 @@ ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, void **res, const char *host)  	/* the easiest way to find a machine account anywhere in the tree  	   is to look for hostname$ */ -	asprintf(&exp, "(samAccountName=%s$)", host); +	if (asprintf(&exp, "(samAccountName=%s$)", host) == -1) { +		DEBUG(1, ("asprintf failed!\n")); +		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); +	} +	  	status = ads_search(ads, res, exp, attrs);  	free(exp);  	return status; @@ -898,13 +940,15 @@ ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods)  	controls[0] = &PermitModify;  	controls[1] = NULL; -	push_utf8_allocate((void **) &utf8_dn, mod_dn); +	if (push_utf8_allocate(&utf8_dn, mod_dn) == -1) { +		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); +	}  	/* find the end of the list, marked by NULL or -1 */  	for(i=0;(mods[i]!=0)&&(mods[i]!=(LDAPMod *) -1);i++);  	/* make sure the end of the list is NULL */  	mods[i] = NULL; -	ret = ldap_modify_ext_s(ads->ld, utf8_dn ? utf8_dn : mod_dn, +	ret = ldap_modify_ext_s(ads->ld, utf8_dn,  				(LDAPMod **) mods, controls, NULL);  	SAFE_FREE(utf8_dn);  	return ADS_ERROR(ret); @@ -922,7 +966,10 @@ ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ADS_MODLIST mods)  	int ret, i;  	char *utf8_dn = NULL; -	push_utf8_allocate((void **) &utf8_dn, new_dn); +	if (push_utf8_allocate(&utf8_dn, new_dn) == -1) { +		DEBUG(1, ("ads_gen_add: push_utf8_allocate failed!")); +		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); +	}  	/* find the end of the list, marked by NULL or -1 */  	for(i=0;(mods[i]!=0)&&(mods[i]!=(LDAPMod *) -1);i++); @@ -944,7 +991,11 @@ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn)  {  	int ret;  	char *utf8_dn = NULL; -	push_utf8_allocate((void **) &utf8_dn, del_dn); +	if (push_utf8_allocate(&utf8_dn, del_dn) == -1) { +		DEBUG(1, ("ads_del_dn: push_utf8_allocate failed!")); +		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); +	} +	  	ret = ldap_delete(ads->ld, utf8_dn ? utf8_dn : del_dn);  	return ADS_ERROR(ret);  } @@ -991,6 +1042,10 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,  	if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm)))  		goto done;  	ou_str = ads_ou_string(org_unit); +	if (!ou_str) { +		DEBUG(1, ("ads_ou_string returned NULL (malloc failure?)\n")); +		goto done; +	}  	new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", hostname, ou_str,   				 ads->config.bind_path);  	free(ou_str); @@ -1320,9 +1375,7 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)  	const char     *attrs[] = {"ntSecurityDescriptor", "objectSid", 0};  	char           *exp     = 0;  	size_t          sd_size = 0; -	struct berval **bvals   = 0;  	struct berval   bval = {0, NULL}; -	prs_struct      ps;  	prs_struct      ps_wire;  	LDAPMessage *res  = 0; @@ -1339,37 +1392,39 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)  	ret = ADS_ERROR(LDAP_SUCCESS); -	asprintf(&exp, "(samAccountName=%s$)", hostname); +	if (asprintf(&exp, "(samAccountName=%s$)", hostname) == -1) { +		DEBUG(1, ("ads_set_machine_sd: asprintf failed!\n")); +		return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); +	} +  	ret = ads_search(ads, (void *) &res, exp, attrs);  	if (!ADS_ERR_OK(ret)) return ret;  	msg   = ads_first_entry(ads, res); -	bvals = ldap_get_values_len(ads->ld, msg, attrs[0]);  	ads_pull_sid(ads, msg, attrs[1], &sid);	 -	ads_msgfree(ads, res); -#if 0 -	file_save("/tmp/sec_desc.old", bvals[0]->bv_val, bvals[0]->bv_len); -#endif -	if (!(ctx = talloc_init_named("sec_io_desc"))) -		return ADS_ERROR(LDAP_NO_MEMORY); - -	prs_init(&ps, bvals[0]->bv_len, ctx, UNMARSHALL); -	prs_append_data(&ps, bvals[0]->bv_val, bvals[0]->bv_len); -	ps.data_offset = 0; -	ldap_value_free_len(bvals); +	if (!(ctx = talloc_init_named("sec_io_desc"))) { +		ret =  ADS_ERROR(LDAP_NO_MEMORY); +		goto ads_set_sd_error; +	} -	if (!sec_io_desc("sd", &psd, &ps, 1)) +	if (!ads_pull_sd(ads, ctx, msg, attrs[0], &psd)) { +		ret = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);  		goto ads_set_sd_error; +	}  	status = sec_desc_add_sid(ctx, &psd, &sid, SEC_RIGHTS_FULL_CTRL, &sd_size); -	if (!NT_STATUS_IS_OK(status)) +	if (!NT_STATUS_IS_OK(status)) { +		ret = ADS_ERROR_NT(status);  		goto ads_set_sd_error; +	}  	prs_init(&ps_wire, sd_size, ctx, MARSHALL); -	if (!sec_io_desc("sd_wire", &psd, &ps_wire, 1)) +	if (!sec_io_desc("sd_wire", &psd, &ps_wire, 1)) { +		ret = ADS_ERROR(LDAP_NO_MEMORY);  		goto ads_set_sd_error; +	}  #if 0  	file_save("/tmp/sec_desc.new", ps_wire.data_p, sd_size); @@ -1381,47 +1436,11 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)  	ads_mod_ber(ctx, &mods, attrs[0], &bval);  	ret = ads_gen_mod(ads, dn, mods); -	prs_mem_free(&ps); -	prs_mem_free(&ps_wire); -	talloc_destroy(ctx); -	return ret; -  ads_set_sd_error: -	prs_mem_free(&ps); +	ads_msgfree(ads, res);  	prs_mem_free(&ps_wire);  	talloc_destroy(ctx); -	return ADS_ERROR(LDAP_NO_MEMORY); -} - -/** - * Set the machine account password - * @param ads connection to ads server - * @param hostname machine whose password is being set - * @param password new password - * @return status of password change - **/ -ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads, -				    const char *hostname,  -				    const char *password) -{ -	ADS_STATUS status; -	char *host = strdup(hostname); -	char *principal;  - -	strlower(host); - -	/* -	  we need to use the '$' form of the name here, as otherwise the -	  server might end up setting the password for a user instead -	 */ -	asprintf(&principal, "%s$@%s", host, ads->auth.realm); -	 -	status = krb5_set_password(ads->auth.kdc_server, principal, password, ads->auth.time_offset); -	 -	free(host); -	free(principal); - -	return status; +	return ret;  }  /** @@ -1596,6 +1615,60 @@ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,  	return count;  } +/** + * pull a SEC_DESC from a ADS result + * @param ads connection to ads server + * @param mem_ctx TALLOC_CTX for allocating sid array + * @param msg Results of search + * @param field Attribute to retrieve + * @param sd Pointer to *SEC_DESC to store result (talloc()ed) + * @return boolean inidicating success +*/ +BOOL ads_pull_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, +		  void *msg, const char *field, SEC_DESC **sd) +{ +	struct berval **values; +	prs_struct      ps; +	BOOL ret = False; + +	values = ldap_get_values_len(ads->ld, msg, field); + +	if (!values) return False; + +	if (values[0]) { +		prs_init(&ps, values[0]->bv_len, mem_ctx, UNMARSHALL); +		prs_append_data(&ps, values[0]->bv_val, values[0]->bv_len); +		ps.data_offset = 0; + +		ret = sec_io_desc("sd", sd, &ps, 1); +	} +	 +	ldap_value_free_len(values); +	return ret; +} + +/*  + * in order to support usernames longer than 21 characters we need to  + * use both the sAMAccountName and the userPrincipalName attributes  + * It seems that not all users have the userPrincipalName attribute set + * + * @param ads connection to ads server + * @param mem_ctx TALLOC_CTX for allocating sid array + * @param msg Results of search + * @return the username + */ +char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, void *msg) +{ +	char *ret, *p; + +	ret = ads_pull_string(ads, mem_ctx, msg, "userPrincipalName"); +	if (ret && (p = strchr(ret, '@'))) { +		*p = 0; +		return ret; +	} +	return ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); +} +  /**   * find the update serial number - this is the core of the ldap cache @@ -1705,8 +1778,9 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)  	ads->config.realm = strdup(p+2);  	ads->config.bind_path = ads_build_dn(ads->config.realm); -	DEBUG(3,("got ldap server name %s@%s\n",  -		 ads->config.ldap_server_name, ads->config.realm)); +	DEBUG(3,("got ldap server name %s@%s, using bind path: %s\n",  +		 ads->config.ldap_server_name, ads->config.realm, +		 ads->config.bind_path));  	ads->config.current_time = ads_parse_time(timestr); diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index f7dd01084a..aa7d99a5f7 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -20,7 +20,7 @@  #include "includes.h" -#ifdef HAVE_ADS +#ifdef HAVE_LDAP  /*      perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can @@ -190,10 +190,12 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)  	}  	DEBUG(3,("got principal=%s\n", principal)); +#ifdef HAVE_KRB5  	if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&  	    got_kerberos_mechanism && ads_kinit_password(ads) == 0) {  		return ads_sasl_spnego_krb5_bind(ads, principal);  	} +#endif  	/* lets do NTLMSSP ... this has the big advantage that we don't need  	   to sync clocks, and we don't rely on special versions of the krb5  diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 4f91ed0f20..228c4a2a08 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -32,74 +32,6 @@ static char *primary_realm;  /* -  a wrapper around ldap_search_s that retries depending on the error code -  this is supposed to catch dropped connections and auto-reconnect -*/ -ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope,  -			       const char *exp, -			       const char **attrs, void **res) -{ -	ADS_STATUS status; -	int count = 3; -	char *bp; - -	if (!ads->ld && -	    time(NULL) - ads->last_attempt < ADS_RECONNECT_TIME) { -		return ADS_ERROR(LDAP_SERVER_DOWN); -	} - -	bp = strdup(bind_path); - -	while (count--) { -		status = ads_do_search_all(ads, bp, scope, exp, attrs, res); -		if (ADS_ERR_OK(status)) { -			DEBUG(5,("Search for %s gave %d replies\n", -				 exp, ads_count_replies(ads, *res))); -			free(bp); -			return status; -		} - -		if (*res) ads_msgfree(ads, *res); -		*res = NULL; -		DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n",  -			 ads->config.realm, ads_errstr(status))); -		if (ads->ld) { -			ldap_unbind(ads->ld);  -		} -		ads->ld = NULL; -		status = ads_connect(ads); -		if (!ADS_ERR_OK(status)) { -			DEBUG(1,("ads_search_retry: failed to reconnect (%s)\n", -				 ads_errstr(status))); -			ads_destroy(&ads); -			free(bp); -			return status; -		} -	} -	free(bp); - -	DEBUG(1,("ads reopen failed after error %s\n", ads_errstr(status))); -	return status; -} - - -ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res,  -			    const char *exp,  -			    const char **attrs) -{ -	return ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE, -				   exp, attrs, res); -} - -ADS_STATUS ads_search_retry_dn(ADS_STRUCT *ads, void **res,  -			       const char *dn,  -			       const char **attrs) -{ -	return ads_do_search_retry(ads, dn, LDAP_SCOPE_BASE, -				   "(objectclass=*)", attrs, res); -} - -/*    return our ads connections structure for a domain. We keep the connection    open to make things faster  */ @@ -166,37 +98,6 @@ static void sid_from_rid(struct winbindd_domain *domain, uint32 rid, DOM_SID *si  	sid_append_rid(sid, rid);  } -/* turn a sAMAccountType into a SID_NAME_USE */ -static enum SID_NAME_USE ads_atype_map(uint32 atype) -{ -	switch (atype & 0xF0000000) { -	case ATYPE_GLOBAL_GROUP: -		return SID_NAME_DOM_GRP; -	case ATYPE_ACCOUNT: -		return SID_NAME_USER; -	default: -		DEBUG(1,("hmm, need to map account type 0x%x\n", atype)); -	} -	return SID_NAME_UNKNOWN; -} - -/*  -   in order to support usernames longer than 21 characters we need to  -   use both the sAMAccountName and the userPrincipalName attributes  -   It seems that not all users have the userPrincipalName attribute set -*/ -static char *pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, void *msg) -{ -	char *ret, *p; - -	ret = ads_pull_string(ads, mem_ctx, msg, "userPrincipalName"); -	if (ret && (p = strchr(ret, '@'))) { -		*p = 0; -		return ret; -	} -	return ads_pull_string(ads, mem_ctx, msg, "sAMAccountName"); -} -  /* Query display info for a realm. This is the basic user list fn */  static NTSTATUS query_user_list(struct winbindd_domain *domain, @@ -254,7 +155,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,  			continue;  		} -		name = pull_username(ads, mem_ctx, msg); +		name = ads_pull_username(ads, mem_ctx, msg);  		gecos = ads_pull_string(ads, mem_ctx, msg, "name");  		if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {  			DEBUG(1,("No sid for %s !?\n", name)); @@ -341,7 +242,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,  				     &account_type) ||  		    !(account_type & ATYPE_GLOBAL_GROUP)) continue; -		name = pull_username(ads, mem_ctx, msg); +		name = ads_pull_username(ads, mem_ctx, msg);  		gecos = ads_pull_string(ads, mem_ctx, msg, "name");  		if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {  			DEBUG(1,("No sid for %s !?\n", name)); @@ -371,63 +272,21 @@ done:  	return status;  } -  /* convert a single name to a sid in a domain */  static NTSTATUS name_to_sid(struct winbindd_domain *domain,  			    const char *name,  			    DOM_SID *sid,  			    enum SID_NAME_USE *type)  { -	ADS_STRUCT *ads = NULL; -	const char *attrs[] = {"objectSid", "sAMAccountType", NULL}; -	int count; -	ADS_STATUS rc; -	void *res = NULL; -	char *exp; -	uint32 t; -	NTSTATUS status = NT_STATUS_UNSUCCESSFUL; +	ADS_STRUCT *ads;  	DEBUG(3,("ads: name_to_sid\n"));  	ads = ads_cached_connection(domain); -	if (!ads) goto done; - -	/* accept either the win2000 or the pre-win2000 username */ -	asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",  -		 name, name, ads->config.realm); -	rc = ads_search_retry(ads, &res, exp, attrs); -	free(exp); -	if (!ADS_ERR_OK(rc)) { -		DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc))); -		goto done; -	} +	if (!ads)  +		return NT_STATUS_UNSUCCESSFUL; -	count = ads_count_replies(ads, res); -	if (count != 1) { -		DEBUG(1,("name_to_sid: %s not found\n", name)); -		goto done; -	} - -	if (!ads_pull_sid(ads, res, "objectSid", sid)) { -		DEBUG(1,("No sid for %s !?\n", name)); -		goto done; -	} - -	if (!ads_pull_uint32(ads, res, "sAMAccountType", &t)) { -		DEBUG(1,("No sAMAccountType for %s !?\n", name)); -		goto done; -	} - -	*type = ads_atype_map(t); - -	status = NT_STATUS_OK; - -	DEBUG(3,("ads name_to_sid mapped %s\n", name)); - -done: -	if (res) ads_msgfree(ads, res); - -	return status; +	return ads_name_to_sid(ads, name, sid, type);  }  /* convert a sid to a user or group name */ @@ -438,46 +297,12 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,  			    enum SID_NAME_USE *type)  {  	ADS_STRUCT *ads = NULL; -	const char *attrs[] = {"userPrincipalName",  -			       "sAMAccountName", -			       "sAMAccountType", NULL}; -	ADS_STATUS rc; -	void *msg = NULL; -	char *exp; -	char *sidstr; -	uint32 atype; -	NTSTATUS status = NT_STATUS_UNSUCCESSFUL; -  	DEBUG(3,("ads: sid_to_name\n")); -  	ads = ads_cached_connection(domain); -	if (!ads) goto done; - -	sidstr = sid_binstring(sid); -	asprintf(&exp, "(objectSid=%s)", sidstr); -	rc = ads_search_retry(ads, &msg, exp, attrs); -	free(exp); -	free(sidstr); -	if (!ADS_ERR_OK(rc)) { -		DEBUG(1,("sid_to_name ads_search: %s\n", ads_errstr(rc))); -		goto done; -	} - -	if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) { -		goto done; -	} - -	*name = pull_username(ads, mem_ctx, msg); -	*type = ads_atype_map(atype); - -	status = NT_STATUS_OK; - -	DEBUG(3,("ads sid_to_name mapped %s\n", *name)); - -done: -	if (msg) ads_msgfree(ads, msg); +	if (!ads)  +		return NT_STATUS_UNSUCCESSFUL; -	return status; +	return ads_sid_to_name(ads, mem_ctx, sid, name, type);  } @@ -504,7 +329,7 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,  		goto failed;  	} -	(*name) = pull_username(ads, mem_ctx, res); +	(*name) = ads_pull_username(ads, mem_ctx, res);  	if (!ads_pull_uint32(ads, res, "sAMAccountType", &atype)) {  		goto failed; @@ -566,7 +391,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,  		goto done;  	} -	info->acct_name = pull_username(ads, mem_ctx, msg); +	info->acct_name = ads_pull_username(ads, mem_ctx, msg);  	info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");  	if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {  		DEBUG(1,("No sid for %d !?\n", user_rid)); diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index c5a2c54511..020a3c6aaf 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -894,7 +894,7 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM  	/* well-known aliases */  	if (sid_equal(sid, &global_sid_Builtin) && !lp_hide_local_users()) { -		enum_group_mapping(SID_NAME_ALIAS, &map, (int *)&num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV); +		enum_group_mapping(SID_NAME_WKN_GRP, &map, (int *)&num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV);  		if (num_entries != 0) {		  			*d_grp=(DOMAIN_GRP *)talloc_zero(ctx, num_entries*sizeof(DOMAIN_GRP)); @@ -1328,7 +1328,7 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM  	    !sid_check_is_in_builtin(&sid))  		return NT_STATUS_OBJECT_TYPE_MISMATCH; -	if (!get_local_group_from_sid(sid, &map, MAPPING_WITHOUT_PRIV)) +	if (!get_group_map_from_sid(sid, &map, MAPPING_WITHOUT_PRIV))  		return NT_STATUS_NO_SUCH_ALIAS;  	switch (q_u->switch_level) { diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index e60a1d2063..f942a685a1 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -313,11 +313,6 @@ static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)  		return WERR_BADFID;  	} -	if (del_a_printer(Printer->dev.handlename) != 0) { -		DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename)); -		return WERR_BADFID; -	} -  	/*   	 * It turns out that Windows allows delete printer on a handle  	 * opened by an admin user, then used on a pipe handle created @@ -342,6 +337,11 @@ static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)  	}  #endif +	if (del_a_printer(Printer->dev.handlename) != 0) { +		DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename)); +		return WERR_BADFID; +	} +  	if (*lp_deleteprinter_cmd()) {  		char *cmd = lp_deleteprinter_cmd(); diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index 202d5b5c88..c040b3cca2 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -4,6 +4,7 @@     Copyright (C) Andrew Tridgell 2002     Copyright (C) Tim Potter 2001,2002 +   Modified by Volker Lendecke 2002     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 @@ -191,7 +192,6 @@ fail:  static NTSTATUS  sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta)  { -	DOM_SID sid;  	fstring s;  	uchar lm_passwd[16], nt_passwd[16]; @@ -227,13 +227,8 @@ sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta)  	/* User and group sid */ -	sid_copy(&sid, get_global_sam_sid()); -	sid_append_rid(&sid, delta->user_rid); -	pdb_set_user_sid(account, &sid); - -	sid_copy(&sid, get_global_sam_sid()); -	sid_append_rid(&sid, delta->group_rid); -	pdb_set_group_sid(account, &sid); +	pdb_set_user_sid_from_rid(account, delta->user_rid); +	pdb_set_group_sid_from_rid(account, delta->group_rid);  	/* Logon and password information */ @@ -359,17 +354,10 @@ fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta)  	fstring sid_string;  	GROUP_MAP map;  	int flag = TDB_INSERT; -	gid_t gid;  	unistr2_to_ascii(name, &delta->uni_grp_name, sizeof(name)-1);  	unistr2_to_ascii(comment, &delta->uni_grp_desc, sizeof(comment)-1); -	if ((grp = getgrnam(name)) == NULL) -		smb_create_group(name, &gid); - -	if ((grp = getgrgid(gid)) == NULL) -		return NT_STATUS_ACCESS_DENIED; -  	/* add the group to the mapping table */  	sid_copy(&group_sid, get_global_sam_sid());  	sid_append_rid(&group_sid, rid); @@ -382,17 +370,17 @@ fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta)  	if (grp == NULL)  	{ -		gid_t new_gid; +		gid_t gid; +  		/* No group found from mapping, find it from its name. */  		if ((grp = getgrnam(name)) == NULL) {  				/* No appropriate group found, create one */  			d_printf("Creating unix group: '%s'\n", name); -			if (smb_create_group(name, &new_gid) != 0) +			if (smb_create_group(name, &gid) != 0) +				return NT_STATUS_ACCESS_DENIED; +			if ((grp = getgrgid(gid)) == NULL)  				return NT_STATUS_ACCESS_DENIED;  		} - -		if ((grp = getgrgid(new_gid)) == NULL) -			return NT_STATUS_ACCESS_DENIED;  	}  	map.gid = grp->gr_gid; @@ -558,22 +546,26 @@ static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta,  	}  	if (grp == NULL) { -		gid_t new_gid; +		gid_t gid; +  		/* No group found from mapping, find it from its name. */  		if ((grp = getgrnam(name)) == NULL) {  				/* No appropriate group found, create one */  			d_printf("Creating unix group: '%s'\n", name); -			if (smb_create_group(name, &new_gid) != 0) +			if (smb_create_group(name, &gid) != 0) +				return NT_STATUS_ACCESS_DENIED; +			if ((grp = getgrgid(gid)) == NULL)  				return NT_STATUS_ACCESS_DENIED;  		} - -		if ((grp = getgrgid(new_gid)) == NULL) -			return NT_STATUS_ACCESS_DENIED;  	}  	map.gid = grp->gr_gid;  	map.sid = alias_sid; -	map.sid_name_use = SID_NAME_ALIAS; + +	if (sid_equal(&dom_sid, &global_sid_Builtin)) +		map.sid_name_use = SID_NAME_WKN_GRP; +	else +		map.sid_name_use = SID_NAME_ALIAS;  	fstrcpy(map.nt_name, name);  	fstrcpy(map.comment, comment);  | 
