Example #1
0
char *alloc_sub_specified(const char *input_string,
			const char *username,
			const char *domain,
			uid_t uid,
			gid_t gid)
{
	char *a_string, *ret_string;
	char *b, *p, *s;

	a_string = SMB_STRDUP(input_string);
	if (a_string == NULL) {
		DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
		return NULL;
	}
	
	for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
		
		b = a_string;
		
		switch (*(p+1)) {
		case 'U' : 
			a_string = realloc_string_sub(a_string, "%U", username);
			break;
		case 'u' : 
			a_string = realloc_string_sub(a_string, "%u", username);
			break;
		case 'G' :
			if (gid != -1) {
				a_string = realloc_string_sub(a_string, "%G", gidtoname(gid));
			} else {
				a_string = realloc_string_sub(a_string, "%G", "NO_GROUP");
			}
			break;
		case 'g' :
			if (gid != -1) {
				a_string = realloc_string_sub(a_string, "%g", gidtoname(gid));
			} else {
				a_string = realloc_string_sub(a_string, "%g", "NO_GROUP");
			}
			break;
		case 'D' :
			a_string = realloc_string_sub(a_string, "%D", domain);
			break;
		case 'N' : 
			a_string = realloc_string_sub(a_string, "%N", automount_server(username)); 
			break;
		default: 
			break;
		}

		p++;
		if (a_string == NULL) {
			return NULL;
		}
	}

	ret_string = alloc_sub_basic(username, a_string);
	SAFE_FREE(a_string);
	return ret_string;
}
Example #2
0
static char * realloc_expand_env_var(char *str, char *p)
{
	char *envname;
	char *envval;
	char *q, *r;
	int copylen;

	if (p[0] != '%' || p[1] != '$' || p[2] != '(') {
		return str;
	}

	/*
	 * Look for the terminating ')'.
	 */

	if ((q = strchr_m(p,')')) == NULL) {
		DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
		return str;
	}

	/*
	 * Extract the name from within the %$(NAME) string.
	 */

	r = p + 3;
	copylen = q - r;
	
	/* reserve space for use later add %$() chars */
	if ( (envname = (char *)SMB_MALLOC(copylen + 1 + 4)) == NULL ) {
		return NULL;
	}
	
	strncpy(envname,r,copylen);
	envname[copylen] = '\0';

	if ((envval = getenv(envname)) == NULL) {
		DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
		SAFE_FREE(envname);
		return str;
	}

	/*
	 * Copy the full %$(NAME) into envname so it
	 * can be replaced.
	 */

	copylen = q + 1 - p;
	strncpy(envname,p,copylen);
	envname[copylen] = '\0';
	r = realloc_string_sub(str, envname, envval);
	SAFE_FREE(envname);
		
	return r;
}
Example #3
0
static char *realloc_expand_longvar(char *str, char *p)
{
	fstring varname;
	char *value;
	char *q, *r;
	int copylen;

	if ( p[0] != '%' || p[1] != '(' ) {
		return str;
	}

	/* Look for the terminating ')'.*/

	if ((q = strchr_m(p,')')) == NULL) {
		DEBUG(0,("realloc_expand_longvar: Unterminated environment variable [%s]\n", p));
		return str;
	}

	/* Extract the name from within the %(NAME) string.*/

	r = p+2;
	copylen = MIN( (q-r), (sizeof(varname)-1) );
	strncpy(varname, r, copylen);
	varname[copylen] = '\0';

	if ((value = get_longvar_val(varname)) == NULL) {
		DEBUG(0,("realloc_expand_longvar: Variable [%s] not set.  Skipping\n", varname));
		return str;
	}

	/* Copy the full %(NAME) into envname so it can be replaced.*/

	copylen = MIN( (q+1-p),(sizeof(varname)-1) );
	strncpy( varname, p, copylen );
	varname[copylen] = '\0';
	r = realloc_string_sub(str, varname, value);
	SAFE_FREE( value );
	
	/* skip over the %(varname) */
	
	return r;
}
Example #4
0
enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) 
{
	NTSTATUS result;
	fstring name_domain, name_user;
	unsigned char trust_passwd[16];
	time_t last_change_time;
	uint32 sec_channel_type;
        NET_USER_INFO_3 info3;
        struct cli_state *cli = NULL;
	uchar chal[8];
	TALLOC_CTX *mem_ctx = NULL;
	DATA_BLOB lm_resp;
	DATA_BLOB nt_resp;
	DOM_CRED ret_creds;
	int attempts = 0;
	unsigned char local_lm_response[24];
	unsigned char local_nt_response[24];
	struct winbindd_domain *contact_domain;
	BOOL retry;

	/* Ensure null termination */
	state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';

	/* Ensure null termination */
	state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';

	DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid,
		  state->request.data.auth.user));

	if (!(mem_ctx = talloc_init("winbind pam auth for %s", state->request.data.auth.user))) {
		DEBUG(0, ("winbindd_pam_auth: could not talloc_init()!\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* Parse domain and username */
	
	parse_domain_user(state->request.data.auth.user, name_domain, name_user);

	/* do password magic */
	
	generate_random_buffer(chal, 8);
	SMBencrypt(state->request.data.auth.pass, chal, local_lm_response);
		
	SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response);

	lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
	nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
	
	/* what domain should we contact? */
	
	if ( IS_DC ) {
		if (!(contact_domain = find_domain_from_name(name_domain))) {
			DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", 
				  state->request.data.auth.user, name_domain, name_user, name_domain)); 
			result = NT_STATUS_NO_SUCH_USER;
			goto done;
		}
		
	} else {
		if (is_myname(name_domain)) {
			DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
			result =  NT_STATUS_NO_SUCH_USER;
			goto done;
		}

		if (!(contact_domain = find_our_domain())) {
			DEBUG(1, ("Authentication for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n", 
				  state->request.data.auth.user, name_domain, name_user)); 
			result = NT_STATUS_NO_SUCH_USER;
			goto done;
		}
	}

	if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
		result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
		goto done;
	}

	/* check authentication loop */

	do {
		ZERO_STRUCT(info3);
		ZERO_STRUCT(ret_creds);
		retry = False;
	
		/* Don't shut this down - it belongs to the connection cache code */
		result = cm_get_netlogon_cli(contact_domain, trust_passwd, 
					     sec_channel_type, False, &cli);

		if (!NT_STATUS_IS_OK(result)) {
			DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
			goto done;
		}

		result = cli_netlogon_sam_network_logon(cli, mem_ctx,
							&ret_creds,
							name_user, name_domain, 
							global_myname(), chal, 
							lm_resp, nt_resp,
							&info3);
		attempts += 1;
		
		/* We have to try a second time as cm_get_netlogon_cli
		   might not yet have noticed that the DC has killed
		   our connection. */

		if ( cli->fd == -1 ) {
			retry = True;
			continue;
		} 
		
		/* if we get access denied, a possible cuase was that we had and open
		   connection to the DC, but someone changed our machine account password
		   out from underneath us using 'net rpc changetrustpw' */
		   
		if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) {
			DEBUG(3,("winbindd_pam_auth: sam_logon returned ACCESS_DENIED.  Maybe the trust account "
				"password was changed and we didn't know it.  Killing connections to domain %s\n",
				name_domain));
			winbindd_cm_flush();
			retry = True;
			cli = NULL;
		} 
		
	} while ( (attempts < 2) && retry );

        if (cli != NULL) {
		/* We might have come out of the loop above with cli == NULL,
		   so don't dereference that. */
		clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
	}
	
	if (NT_STATUS_IS_OK(result)) {
		netsamlogon_cache_store( cli->mem_ctx, &info3 );
		wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);

		/* Check if the user is in the right group */

		if (!NT_STATUS_IS_OK(result = check_info3_in_group(mem_ctx, &info3, state->request.data.auth.required_membership_sid))) {
			DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
				  state->request.data.auth.user, 
				  state->request.data.auth.required_membership_sid));
		}
	}

done:
	/* give us a more useful (more correct?) error code */
	if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
		result = NT_STATUS_NO_LOGON_SERVERS;
	}
	
	state->response.data.auth.nt_status = NT_STATUS_V(result);
	fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));

	/* we might have given a more useful error above */
	if (!*state->response.data.auth.error_string) 
		fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
	state->response.data.auth.pam_error = nt_status_to_pam(result);

	DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", 
	      state->request.data.auth.user, 
	      state->response.data.auth.nt_status_string,
	      state->response.data.auth.pam_error));	      

	if ( NT_STATUS_IS_OK(result) &&
	     (state->request.flags & WBFLAG_PAM_AFS_TOKEN) ) {

		char *afsname = strdup(lp_afs_username_map());
		char *cell;

		if (afsname == NULL) goto no_token;

		afsname = realloc_string_sub(afsname, "%D", name_domain);
		afsname = realloc_string_sub(afsname, "%u", name_user);
		afsname = realloc_string_sub(afsname, "%U", name_user);

		if (afsname == NULL) goto no_token;

		strlower_m(afsname);

		cell = strchr(afsname, '@');

		if (cell == NULL) goto no_token;

		*cell = '\0';
		cell += 1;

		/* Append an AFS token string */
		state->response.extra_data =
			afs_createtoken_str(afsname, cell);

		if (state->response.extra_data != NULL)
			state->response.length +=
				strlen(state->response.extra_data)+1;

	no_token:
		SAFE_FREE(afsname);
	}
		
	if (mem_ctx) 
		talloc_destroy(mem_ctx);
	
	return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
Example #5
0
char *alloc_sub_advanced(int snum, const char *user, 
				  const char *connectpath, gid_t gid, 
				  const char *smb_name, const char *str)
{
	char *a_string, *ret_string;
	char *b, *p, *s, *t, *h;

	a_string = strdup(str);
	if (a_string == NULL) {
		DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
		return NULL;
	}
	
	for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
		
		b = t = a_string;
		
		switch (*(p+1)) {
		case 'N' :
			t = realloc_string_sub(t, "%N", automount_server(user));
			break;
		case 'H':
			if ((h = get_user_home_dir(user)))
				t = realloc_string_sub(t, "%H", h);
			break;
		case 'P': 
			t = realloc_string_sub(t, "%P", connectpath); 
			break;
		case 'S': 
			t = realloc_string_sub(t, "%S", lp_servicename(snum)); 
			break;
		case 'g': 
			t = realloc_string_sub(t, "%g", gidtoname(gid)); 
			break;
		case 'u': 
			t = realloc_string_sub(t, "%u", user); 
			break;
			
			/* Patch from [email protected] Left the %N (NIS
			 * server name) in standard_sub_basic as it is
			 * a feature for logon servers, hence uses the
			 * username.  The %p (NIS server path) code is
			 * here as it is used instead of the default
			 * "path =" string in [homes] and so needs the
			 * service name, not the username.  */
		case 'p': 
			t = realloc_string_sub(t, "%p", automount_path(lp_servicename(snum))); 
			break;
			
		default: 
			break;
		}

		p++;
		if (t == NULL) {
			SAFE_FREE(a_string);
			return NULL;
		}
		a_string = t;
	}

	ret_string = alloc_sub_basic(smb_name, a_string);
	SAFE_FREE(a_string);
	return ret_string;
}
Example #6
0
char *alloc_sub_basic(const char *smb_name, const char *str)
{
	char *b, *p, *s, *t, *r, *a_string;
	fstring pidstr;
	struct passwd *pass;
	const char *local_machine_name = get_local_machine_name();

	/* workaround to prevent a crash while lookinf at bug #687 */
	
	if ( !str ) {
		DEBUG(0,("alloc_sub_basic: NULL source string!  This should not happen\n"));
		return NULL;
	}
	
	a_string = strdup(str);
	if (a_string == NULL) {
		DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
		return NULL;
	}
	
	for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {

		r = NULL;
		b = t = a_string;
		
		switch (*(p+1)) {
		case 'U' : 
			r = strdup_lower(smb_name);
			if (r == NULL) goto error;
			t = realloc_string_sub(t, "%U", r);
			break;
		case 'G' :
			r = strdup(smb_name);
			if (r == NULL) goto error;
			if ((pass = Get_Pwnam(r))!=NULL) {
				t = realloc_string_sub(t, "%G", gidtoname(pass->pw_gid));
			} 
			break;
		case 'D' :
			r = strdup_upper(current_user_info.domain);
			if (r == NULL) goto error;
			t = realloc_string_sub(t, "%D", r);
			break;
		case 'I' :
			t = realloc_string_sub(t, "%I", client_addr());
			break;
		case 'L' : 
			if (local_machine_name && *local_machine_name)
				t = realloc_string_sub(t, "%L", local_machine_name); 
			else
				t = realloc_string_sub(t, "%L", global_myname()); 
			break;
		case 'N':
			t = realloc_string_sub(t, "%N", automount_server(smb_name));
			break;
		case 'M' :
			t = realloc_string_sub(t, "%M", client_name());
			break;
		case 'R' :
			t = realloc_string_sub(t, "%R", remote_proto);
			break;
		case 'T' :
			t = realloc_string_sub(t, "%T", timestring(False));
			break;
		case 'a' :
			t = realloc_string_sub(t, "%a", remote_arch);
			break;
		case 'd' :
			slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
			t = realloc_string_sub(t, "%d", pidstr);
			break;
		case 'h' :
			t = realloc_string_sub(t, "%h", myhostname());
			break;
		case 'm' :
			t = realloc_string_sub(t, "%m", remote_machine);
			break;
		case 'v' :
			t = realloc_string_sub(t, "%v", SAMBA_VERSION_STRING);
			break;
		case '$' :
			t = realloc_expand_env_var(t, p); /* Expand environment variables */
			break;
			
		default: 
			break;
		}

		p++;
		SAFE_FREE(r);
		if (t == NULL) goto error;
		a_string = t;
	}

	return a_string;
error:
	SAFE_FREE(a_string);
	return NULL;
}