Beispiel #1
0
static BOOL set_privileges( const DOM_SID *sid, SE_PRIV *mask )
{
	TDB_CONTEXT *tdb = get_account_pol_tdb();
	fstring keystr;
	TDB_DATA key, data;
	
	if ( !lp_enable_privileges() )
		return False;

	if ( !tdb )
		return False;

	if ( !sid || (sid->num_auths == 0) ) {
		DEBUG(0,("set_privileges: Refusing to store empty SID!\n"));
		return False;
	}

	/* PRIV_<SID> (NULL terminated) as the key */
	
	fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
	key.dptr = keystr;
	key.dsize = strlen(keystr) + 1;
	
	/* no packing.  static size structure, just write it out */
	
	data.dptr  = (char*)mask;
	data.dsize = sizeof(SE_PRIV);

	return ( tdb_store(tdb, key, data, TDB_REPLACE) != -1 );
}
Beispiel #2
0
enum winbindd_result winbindd_domain_info(struct winbindd_cli_state *state)
{
	struct winbindd_domain *domain;

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

	domain = find_domain_from_name(state->request.domain_name);

	if (domain == NULL) {
		DEBUG(3, ("Did not find domain [%s]\n",
			  state->request.domain_name));
		return WINBINDD_ERROR;
	}

	fstrcpy(state->response.data.domain_info.name, domain->name);
	fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name);
	fstrcpy(state->response.data.domain_info.sid,
		sid_string_static(&domain->sid));
	
	state->response.data.domain_info.native_mode = domain->native_mode;
	state->response.data.domain_info.active_directory = domain->active_directory;
	state->response.data.domain_info.primary = domain->primary;

	state->response.data.domain_info.sequence_number =
		domain->sequence_number;

	return WINBINDD_OK;
}
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain, 
			   TALLOC_CTX *mem_ctx, 
			   DOM_SID *user_sid, 
			   WINBIND_USERINFO *info)
{
	struct winbind_cache *cache = get_cache(domain);
	struct cache_entry *centry = NULL;
	NTSTATUS status;

	if (!cache->tdb)
		goto do_query;

	centry = wcache_fetch(cache, domain, "U/%s", sid_string_static(user_sid));
	
	/* If we have an access denied cache entry and a cached info3 in the
           samlogon cache then do a query.  This will force the rpc back end
           to return the info3 data. */

	if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) &&
	    netsamlogon_cache_have(user_sid)) {
		DEBUG(10, ("query_user: cached access denied and have cached info3\n"));
		domain->last_status = NT_STATUS_OK;
		centry_free(centry);
		goto do_query;
	}
	
	if (!centry)
		goto do_query;

	info->acct_name = centry_string(centry, mem_ctx);
	info->full_name = centry_string(centry, mem_ctx);
	info->user_sid = centry_sid(centry, mem_ctx);
	info->group_sid = centry_sid(centry, mem_ctx);
	status = centry->status;

	DEBUG(10,("query_user: [Cached] - cached info for domain %s status %s\n",
		domain->name, get_friendly_nt_error_msg(status) ));

	centry_free(centry);
	return status;

do_query:
	ZERO_STRUCTP(info);

	/* Return status value returned by seq number check */

	if (!NT_STATUS_IS_OK(domain->last_status))
		return domain->last_status;
	
	DEBUG(10,("sid_to_name: [Cached] - doing backend query for info for domain %s\n",
		domain->name ));

	status = domain->backend->query_user(domain, mem_ctx, user_sid, info);

	/* and save it */
	refresh_sequence_number(domain, False);
	wcache_save_user(domain, status, info);

	return status;
}
Beispiel #4
0
NTSTATUS idmap_cache_build_sidkey(TALLOC_CTX *ctx, char **sidkey, const struct id_map *id)
{
	*sidkey = talloc_asprintf(ctx, "IDMAP/SID/%s", sid_string_static(id->sid));
	if ( ! *sidkey) {
		DEBUG(1, ("failed to build sidkey, OOM?\n"));
		return NT_STATUS_NO_MEMORY;
	}

	return NT_STATUS_OK;
}
Beispiel #5
0
BOOL afs_login(connection_struct *conn)
{
	DATA_BLOB ticket;
	pstring afs_username;
	char *cell;
	BOOL result;
	char *ticket_str;
	DOM_SID user_sid;

	struct ClearToken ct;

	pstrcpy(afs_username, lp_afs_username_map());
	standard_sub_conn(conn, afs_username, sizeof(afs_username));

	if (NT_STATUS_IS_OK(uid_to_sid(&user_sid, conn->uid)))
		pstring_sub(afs_username, "%s", sid_string_static(&user_sid));

	/* The pts command always generates completely lower-case user
	 * names. */
	strlower_m(afs_username);

	cell = strchr(afs_username, '@');

	if (cell == NULL) {
		DEBUG(1, ("AFS username doesn't contain a @, "
			  "could not find cell\n"));
		return False;
	}

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

	DEBUG(10, ("Trying to log into AFS for user %s@%s\n", 
		   afs_username, cell));

	if (!afs_createtoken(afs_username, cell, &ticket, &ct))
		return False;

	/* For which Unix-UID do we want to set the token? */
	ct.ViceId = getuid();

	ticket_str = afs_encode_token(cell, ticket, &ct);

	result = afs_settoken_str(ticket_str);

	SAFE_FREE(ticket_str);

	data_blob_free(&ticket);

	return result;
}
Beispiel #6
0
static BOOL get_privileges( const DOM_SID *sid, SE_PRIV *mask )
{
	TDB_CONTEXT *tdb = get_account_pol_tdb();
	fstring keystr;
	TDB_DATA key, data;

	/* Fail if the admin has not enable privileges */
	
	if ( !lp_enable_privileges() ) {
		return False;
	}
	
	if ( !tdb )
		return False;

	/* PRIV_<SID> (NULL terminated) as the key */
	
	fstr_sprintf( keystr, "%s%s", PRIVPREFIX, sid_string_static(sid) );
	key.dptr = keystr;
	key.dsize = strlen(keystr) + 1;

	data = tdb_fetch( tdb, key );
	
	if ( !data.dptr ) {
		DEBUG(3,("get_privileges: No privileges assigned to SID [%s]\n",
			sid_string_static(sid)));
		return False;
	}
	
	SMB_ASSERT( data.dsize == sizeof( SE_PRIV ) );
	
	se_priv_copy( mask, (SE_PRIV*)data.dptr );
	SAFE_FREE(data.dptr);

	return True;
}
Beispiel #7
0
void dump_ntquota(SMB_NTQUOTA_STRUCT *qt, BOOL _verbose, BOOL _numeric, void (*_sidtostring)(fstring str, DOM_SID *sid, BOOL _numeric))
{
	if (!qt)
		smb_panic("dump_ntquota() called with NULL pointer");

	switch (qt->qtype) {
		case SMB_USER_FS_QUOTA_TYPE:
			{
				d_printf("File System QUOTAS:\n");
				d_printf("Limits:\n");
				d_printf(" Default Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
				d_printf(" Default Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
				d_printf("Quota Flags:\n");
				d_printf(" Quotas Enabled: %s\n",
					((qt->qflags&QUOTAS_ENABLED)||(qt->qflags&QUOTAS_DENY_DISK))?"On":"Off");
				d_printf(" Deny Disk:      %s\n",(qt->qflags&QUOTAS_DENY_DISK)?"On":"Off");
				d_printf(" Log Soft Limit: %s\n",(qt->qflags&QUOTAS_LOG_THRESHOLD)?"On":"Off");
				d_printf(" Log Hard Limit: %s\n",(qt->qflags&QUOTAS_LOG_LIMIT)?"On":"Off");
			}
			break;
		case SMB_USER_QUOTA_TYPE:
			{
				fstring username_str = {0};
				
				if (_sidtostring) {
					_sidtostring(username_str,&qt->sid,_numeric);
				} else {
					fstrcpy(username_str,sid_string_static(&qt->sid));
				}

				if (_verbose) {	
					d_printf("Quotas for User: %s\n",username_str);
					d_printf("Used Space: %15s\n",quota_str_static(qt->usedspace,False,_numeric));
					d_printf("Soft Limit: %15s\n",quota_str_static(qt->softlim,True,_numeric));
					d_printf("Hard Limit: %15s\n",quota_str_static(qt->hardlim,True,_numeric));
				} else {
					d_printf("%-30s: ",username_str);
					d_printf("%15s/",quota_str_static(qt->usedspace,False,_numeric));
					d_printf("%15s/",quota_str_static(qt->softlim,True,_numeric));
					d_printf("%15s\n",quota_str_static(qt->hardlim,True,_numeric));
				}
			}
			break;
		default:
			d_printf("dump_ntquota() invalid qtype(%d)\n",qt->qtype);
			return;
	}
}
Beispiel #8
0
static char *longvar_domainsid( void )
{
	DOM_SID sid;
	char *sid_string;
	
	if ( !secrets_fetch_domain_sid( lp_workgroup(), &sid ) ) {
		return NULL;
	}
	
	sid_string = SMB_STRDUP( sid_string_static( &sid ) );
	
	if ( !sid_string ) {
		DEBUG(0,("longvar_domainsid: failed to dup SID string!\n"));
	}
	
	return sid_string;
}
Beispiel #9
0
static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli, 
					 TALLOC_CTX *mem_ctx, int argc, 
					 const char **argv) 
{
	POLICY_HND dom_pol;
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;

	DOM_SID sid;
	uint32 count;
	char **rights;

	int i;

	if (argc != 2 ) {
		printf("Usage: %s SID\n", argv[0]);
		return NT_STATUS_OK;
	}

	result = name_to_sid(cli, mem_ctx, &sid, argv[1]);
	if (!NT_STATUS_IS_OK(result))
		goto done;	

	result = cli_lsa_open_policy2(cli, mem_ctx, True, 
				     SEC_RIGHTS_MAXIMUM_ALLOWED,
				     &dom_pol);

	if (!NT_STATUS_IS_OK(result))
		goto done;

	result = cli_lsa_enum_account_rights(cli, mem_ctx, &dom_pol, &sid, &count, &rights);

	if (!NT_STATUS_IS_OK(result))
		goto done;

	printf("found %d privileges for SID %s\n", count, sid_string_static(&sid));

	for (i = 0; i < count; i++) {
		printf("\t%s\n", rights[i]);
	}

 done:
	return result;
}
Beispiel #10
0
BOOL revoke_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask)
{
	SE_PRIV mask;
	
	/* if the user has no privileges, then we can't revoke any */
	
	if ( !get_privileges( sid, &mask ) )
		return True;
	
	DEBUG(10,("revoke_privilege: %s\n", sid_string_static(sid)));
	
	DEBUGADD( 10, ("original privilege mask:\n"));
	dump_se_priv( DBGC_ALL, 10, &mask );

	se_priv_remove( &mask, priv_mask );
	
	DEBUGADD( 10, ("new privilege mask:\n"));
	dump_se_priv( DBGC_ALL, 10, &mask );
	
	return set_privileges( sid, &mask );
}
Beispiel #11
0
/* Lookup groups a user is a member of.  I wish Unix had a call like this! */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
				  TALLOC_CTX *mem_ctx,
				  const DOM_SID *user_sid,
				  uint32 *num_groups, DOM_SID ***user_grpsids)
{
	CLI_POLICY_HND *hnd;
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	POLICY_HND dom_pol, user_pol;
	uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
	BOOL got_dom_pol = False, got_user_pol = False;
	DOM_GID *user_groups;
	unsigned int i;
	unsigned int retry;
	fstring sid_string;
	uint32 user_rid;
	NET_USER_INFO_3 *user;

	DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));

	*num_groups = 0;
	*user_grpsids = NULL;

	/* so lets see if we have a cached user_info_3 */
	
	if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
	{
		DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
			sid_string_static(user_sid)));
			
		*num_groups = user->num_groups;
				
		(*user_grpsids) = TALLOC_ARRAY(mem_ctx, DOM_SID*, *num_groups);
		for (i=0;i<(*num_groups);i++) {
			(*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
		}
				
		SAFE_FREE(user);
				
		return NT_STATUS_OK;
	}
Beispiel #12
0
static NTSTATUS enum_privileges_for_accounts( TALLOC_CTX *ctx, struct cli_state *cli,
                                              POLICY_HND *pol )
{
	NTSTATUS result;
	uint32 enum_context=0;
	uint32 pref_max_length=0x1000;
	DOM_SID *sids;
	uint32 count=0;
	int i;
	fstring name;

	result = cli_lsa_enum_sids(cli, ctx, pol, &enum_context, 
		pref_max_length, &count, &sids);

	if (!NT_STATUS_IS_OK(result))
		return result;
		
	for ( i=0; i<count; i++ ) {
	
		/* try to convert the SID to a name.  Fall back to 
		   printing the raw SID if necessary */
		   
		result = sid_to_name( cli, ctx, &sids[i], name );
		if ( !NT_STATUS_IS_OK (result) )
			fstrcpy( name, sid_string_static(&sids[i]) );
			
		d_printf("%s\n", name);
		
		result = enum_privileges_for_user( ctx, cli, pol, &sids[i] );
		
		if ( !NT_STATUS_IS_OK(result) )
			return result;

		d_printf("\n");
	}

	return NT_STATUS_OK;
}
Beispiel #13
0
int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, SMB_NTQUOTA_STRUCT *qt)
{
	int ret;
	SMB_DISK_QUOTA D;
	unid_t id;

	ZERO_STRUCT(D);

	if (!fsp||!fsp->conn||!qt)
		return (-1);

	ZERO_STRUCT(*qt);

	id.uid = -1;

	if (psid && !sid_to_uid(psid, &id.uid)) {
		DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
			sid_string_static(psid)));	
	}

	ret = SMB_VFS_GET_QUOTA(fsp->conn, qtype, id, &D);

	if (psid)
		qt->sid    = *psid;

	if (ret!=0) {
		return ret;
	}
		
	qt->usedspace = (SMB_BIG_UINT)D.curblocks*D.bsize;
	qt->softlim = limit_unix2nt(D.softlimit, D.bsize);
	qt->hardlim = limit_unix2nt(D.hardlimit, D.bsize);
	qt->qflags = D.qflags;

	
	return 0;
}
Beispiel #14
0
BOOL grant_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask)
{
	SE_PRIV old_mask, new_mask;
	
	ZERO_STRUCT( old_mask );
	ZERO_STRUCT( new_mask );

	if ( get_privileges( sid, &old_mask ) )
		se_priv_copy( &new_mask, &old_mask );
	else
		se_priv_copy( &new_mask, &se_priv_none );

	se_priv_add( &new_mask, priv_mask );

	DEBUG(10,("grant_privilege: %s\n", sid_string_static(sid)));
	
	DEBUGADD( 10, ("original privilege mask:\n"));
	dump_se_priv( DBGC_ALL, 10, &old_mask );
	
	DEBUGADD( 10, ("new privilege mask:\n"));
	dump_se_priv( DBGC_ALL, 10, &new_mask );
	
	return set_privileges( sid, &new_mask );
}
Beispiel #15
0
BOOL get_privileges_for_sids(SE_PRIV *privileges, DOM_SID *slist, int scount)
{
	SE_PRIV mask;
	int i;
	BOOL found = False;

	se_priv_copy( privileges, &se_priv_none );
	
	for ( i=0; i<scount; i++ ) {
		/* don't add unless we actually have a privilege assigned */

		if ( !get_privileges( &slist[i], &mask ) )
			continue;

		DEBUG(5,("get_privileges_for_sids: sid = %s\nPrivilege set:\n", 
			sid_string_static(&slist[i])));
		dump_se_priv( DBGC_ALL, 5, &mask );
			
		se_priv_add( privileges, &mask );
		found = True;
	}

	return found;
}
Beispiel #16
0
/*
  convert a domain SID to a user or group name
*/
NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
			    TALLOC_CTX *mem_ctx,
			    const DOM_SID *sid,
			    char **domain_name,
			    char **name,
			    enum SID_NAME_USE *type)
{
	CLI_POLICY_HND *hnd;
	char **domains;
	char **names;
	uint32 *types;
	NTSTATUS result;
	int retry;

	DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid),
			domain->name ));

	retry = 0;
	do {
		if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
			return result;
        
		result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
					     1, sid, &domains, &names, &types);
	} while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
			hnd && hnd->cli && hnd->cli->fd == -1);

	if (NT_STATUS_IS_OK(result)) {
		*type = (enum SID_NAME_USE)types[0];
		*domain_name = domains[0];
		*name = names[0];
		DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
	}

	return result;
}
Beispiel #17
0
NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains, int *num_domains, TRUSTDOM ***domains)
{
	TDB_LIST_NODE *keys, *k;
	TRUSTDOM *dom = NULL;
	char *pattern;
	unsigned int start_idx;
	uint32 idx = 0;
	size_t size, packed_size = 0;
	fstring dom_name;
	char *packed_pass;
	struct trusted_dom_pass *pass = talloc_zero(ctx, sizeof(struct trusted_dom_pass));
	NTSTATUS status;

	if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
	
	if (!pass) {
		DEBUG(0, ("talloc_zero failed!\n"));
		return NT_STATUS_NO_MEMORY;
	}
				
	*num_domains = 0;
	start_idx = *enum_ctx;

	/* generate searching pattern */
	if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) {
		DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n", 
		  max_num_domains, *enum_ctx));

	*domains = talloc_zero(ctx, sizeof(**domains)*max_num_domains);

	/* fetching trusted domains' data and collecting them in a list */
	keys = tdb_search_keys(tdb, pattern);

	/* 
	 * if there's no keys returned ie. no trusted domain,
	 * return "no more entries" code
	 */
	status = NT_STATUS_NO_MORE_ENTRIES;

	/* searching for keys in secrets db -- way to go ... */
	for (k = keys; k; k = k->next) {
		char *secrets_key;
		
		/* important: ensure null-termination of the key string */
		secrets_key = strndup(k->node_key.dptr, k->node_key.dsize);
		if (!secrets_key) {
			DEBUG(0, ("strndup failed!\n"));
			return NT_STATUS_NO_MEMORY;
		}

		packed_pass = secrets_fetch(secrets_key, &size);
		packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass);
		/* packed representation isn't needed anymore */
		SAFE_FREE(packed_pass);
		
		if (size != packed_size) {
			DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key));
			continue;
		}
		
		pull_ucs2_fstring(dom_name, pass->uni_name);
		DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
			   idx, dom_name, sid_string_static(&pass->domain_sid)));

		SAFE_FREE(secrets_key);

		if (idx >= start_idx && idx < start_idx + max_num_domains) {
			dom = talloc_zero(ctx, sizeof(*dom));
			if (!dom) {
				/* free returned tdb record */
				return NT_STATUS_NO_MEMORY;
			}
			
			/* copy domain sid */
			SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid));
			memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid));
			
			/* copy unicode domain name */
			dom->name = talloc_strdup_w(ctx, pass->uni_name);
			
			(*domains)[idx - start_idx] = dom;
			
			DEBUG(18, ("Secret record is in required range.\n \
				   start_idx = %d, max_num_domains = %d. Added to returned array.\n",
				   start_idx, max_num_domains));

			*enum_ctx = idx + 1;
			(*num_domains)++;
		
			/* set proper status code to return */
			if (k->next) {
				/* there are yet some entries to enumerate */
				status = STATUS_MORE_ENTRIES;
			} else {
				/* this is the last entry in the whole enumeration */
				status = NT_STATUS_OK;
			}
		} else {
Beispiel #18
0
static int print_sam_info (struct samu *sam_pwent, BOOL verbosity, BOOL smbpwdstyle)
{
	uid_t uid;
	time_t tmp;

	/* TODO: chaeck if entry is a user or a workstation */
	if (!sam_pwent) return -1;
	
	if (verbosity) {
		pstring temp;
		const uint8 *hours;
		
		printf ("Unix username:        %s\n", pdb_get_username(sam_pwent));
		printf ("NT username:          %s\n", pdb_get_nt_username(sam_pwent));
		printf ("Account Flags:        %s\n", pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent), NEW_PW_FORMAT_SPACE_PADDED_LEN));
		printf ("User SID:             %s\n",
			sid_string_static(pdb_get_user_sid(sam_pwent)));
		printf ("Primary Group SID:    %s\n",
			sid_string_static(pdb_get_group_sid(sam_pwent)));
		printf ("Full Name:            %s\n", pdb_get_fullname(sam_pwent));
		printf ("Home Directory:       %s\n", pdb_get_homedir(sam_pwent));
		printf ("HomeDir Drive:        %s\n", pdb_get_dir_drive(sam_pwent));
		printf ("Logon Script:         %s\n", pdb_get_logon_script(sam_pwent));
		printf ("Profile Path:         %s\n", pdb_get_profile_path(sam_pwent));
		printf ("Domain:               %s\n", pdb_get_domain(sam_pwent));
		printf ("Account desc:         %s\n", pdb_get_acct_desc(sam_pwent));
		printf ("Workstations:         %s\n", pdb_get_workstations(sam_pwent));
		printf ("Munged dial:          %s\n", pdb_get_munged_dial(sam_pwent));
		
		tmp = pdb_get_logon_time(sam_pwent);
		printf ("Logon time:           %s\n", tmp ? http_timestring(tmp) : "0");
		
		tmp = pdb_get_logoff_time(sam_pwent);
		printf ("Logoff time:          %s\n", tmp ? http_timestring(tmp) : "0");
		
		tmp = pdb_get_kickoff_time(sam_pwent);
		printf ("Kickoff time:         %s\n", tmp ? http_timestring(tmp) : "0");
		
		tmp = pdb_get_pass_last_set_time(sam_pwent);
		printf ("Password last set:    %s\n", tmp ? http_timestring(tmp) : "0");
		
		tmp = pdb_get_pass_can_change_time(sam_pwent);
		printf ("Password can change:  %s\n", tmp ? http_timestring(tmp) : "0");
		
		tmp = pdb_get_pass_must_change_time(sam_pwent);
		printf ("Password must change: %s\n", tmp ? http_timestring(tmp) : "0");

		tmp = pdb_get_bad_password_time(sam_pwent);
		printf ("Last bad password   : %s\n", tmp ? http_timestring(tmp) : "0");
		printf ("Bad password count  : %d\n", 
			pdb_get_bad_password_count(sam_pwent));
		
		hours = pdb_get_hours(sam_pwent);
		pdb_sethexhours(temp, hours);
		printf ("Logon hours         : %s\n", temp);
		
	} else if (smbpwdstyle) {
		char lm_passwd[33];
		char nt_passwd[33];

		uid = nametouid(pdb_get_username(sam_pwent));
		pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
		pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent));
			
		printf("%s:%lu:%s:%s:%s:LCT-%08X:\n",
		       pdb_get_username(sam_pwent),
		       (unsigned long)uid,
		       lm_passwd,
		       nt_passwd,
		       pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN),
		       (uint32)convert_time_t_to_uint32(pdb_get_pass_last_set_time(sam_pwent)));
	} else {
		uid = nametouid(pdb_get_username(sam_pwent));
		printf ("%s:%lu:%s\n", pdb_get_username(sam_pwent), (unsigned long)uid,	
			pdb_get_fullname(sam_pwent));
	}

	return 0;
}
Beispiel #19
0
int main(int argc, char **argv) {
   int i;
   int result;
   char **names;
   int num_names;
   int num_sids;
   CacServerHandle *hnd = NULL;
   POLICY_HND *lsa_pol  = NULL;
   TALLOC_CTX *mem_ctx  = NULL;

   DOM_SID *sid_buf     = NULL;

   BOOL sim_partial     = False;

   if(argc > 1 && strcmp(argv[1], "-p") == 0)
      sim_partial = True;

   mem_ctx = talloc_init("lsaq");

   hnd = cac_NewServerHandle(False);

   fill_conn_info(hnd);

   get_server_names(mem_ctx, &num_names, &names);

   /*connect to the PDC and open a LSA handle*/
   if(!cac_Connect(hnd, NULL)) {
      fprintf(stderr, "Could not connect to server.\n Error %s.\n", nt_errstr(hnd->status));
      cac_FreeHandle(hnd);
      exit(-1);
   }

   fprintf(stdout, "Connected to server: %s\n", hnd->server);

   struct LsaOpenPolicy lop;
   ZERO_STRUCT(lop);

   lop.in.access = SEC_RIGHT_MAXIMUM_ALLOWED;
   lop.in.security_qos = True;

   if(!cac_LsaOpenPolicy(hnd, mem_ctx, &lop)) {
      fprintf(stderr, "Could not get lsa policy handle.\n Error: %s\n", nt_errstr(hnd->status));
      cac_FreeHandle(hnd);
      exit(-1);
   }

   fprintf(stdout, "Opened Policy Handle\n");

   /*just to make things neater*/
   lsa_pol = lop.out.pol;

   /*fetch the local sid and domain sid for the pdc*/

   struct LsaFetchSid fsop;
   ZERO_STRUCT(fsop);

   fsop.in.pol = lsa_pol;
   fsop.in.info_class = (CAC_LOCAL_INFO|CAC_DOMAIN_INFO);

   fprintf(stdout, "fetching SID info for %s\n", hnd->server);

   result = cac_LsaFetchSid(hnd, mem_ctx, &fsop);
   if(!result) {
      fprintf(stderr, "Could not get sid for server: %s\n. Error: %s\n", hnd->server, nt_errstr(hnd->status));
      cac_FreeHandle(hnd);
      talloc_destroy(mem_ctx);
      exit(-1);
   }

   if(result == CAC_PARTIAL_SUCCESS) {
      fprintf(stdout, "could not retrieve both domain and local information\n");
   }
   

   fprintf(stdout, "Fetched SID info for %s\n", hnd->server);
   if(fsop.out.local_sid != NULL)
      fprintf(stdout, " domain: %s. Local SID: %s\n", fsop.out.local_sid->domain, sid_string_static(&fsop.out.local_sid->sid));

   if(fsop.out.domain_sid != NULL)
      fprintf(stdout, " domain: %s, Domain SID: %s\n", fsop.out.domain_sid->domain, sid_string_static(&fsop.out.domain_sid->sid));

   fprintf(stdout, "Looking up sids\n");

   
   struct LsaGetSidsFromNames gsop;
   ZERO_STRUCT(gsop);
   
   gsop.in.pol       = lsa_pol;
   gsop.in.num_names = num_names;
   gsop.in.names     = names;

   result = cac_LsaGetSidsFromNames(hnd, mem_ctx, &gsop);

   if(!result) {
      fprintf(stderr, "Could not lookup any sids!\n Error: %s\n", nt_errstr(hnd->status));
      goto done;
   }

   if(result == CAC_PARTIAL_SUCCESS) {
      fprintf(stdout, "Not all names could be looked up.\nThe following names were not found:\n");
      
      for(i = 0; i < (num_names - gsop.out.num_found); i++) {
         fprintf(stdout, " %s\n", gsop.out.unknown[i]);
      }
      
      fprintf(stdout, "\n");
   }

   /*buffer the sids so we can look them up back to names*/
   num_sids = (sim_partial) ? gsop.out.num_found + 2: gsop.out.num_found;
   sid_buf = TALLOC_ARRAY(mem_ctx, DOM_SID, num_sids);

   fprintf(stdout, "%d names were resolved: \n", gsop.out.num_found);


   i = 0;
   while(i < gsop.out.num_found) {
      fprintf(stdout, " Name: %s\n SID: %s\n\n", gsop.out.sids[i].name, sid_string_static(&gsop.out.sids[i].sid));

      sid_buf[i] = gsop.out.sids[i].sid;

      printf("Attempting to open account\n");

      struct LsaOpenAccount loa;
      ZERO_STRUCT(loa);

      loa.in.pol    = lsa_pol;
      loa.in.access = SEC_RIGHT_MAXIMUM_ALLOWED;
      loa.in.sid    = &gsop.out.sids[i].sid;

      if(!cac_LsaOpenAccount(hnd, mem_ctx, &loa)) {
         fprintf(stderr, "Could not open account.\n Error: %s\n", nt_errstr(hnd->status));
      }

      printf("\nEnumerating privs:");
      struct LsaEnumAccountRights earop;
      ZERO_STRUCT(earop);

      earop.in.pol = lsa_pol;

      earop.in.sid = &gsop.out.sids[i].sid;

      if(!cac_LsaEnumAccountRights(hnd, mem_ctx, &earop)) {
         fprintf(stderr, "Could not enumerate account rights.\n Error: %s\n", nt_errstr(hnd->status));
      }

      int j;
      printf( "Rights: ");
      for(j = 0; j < earop.out.num_privs; j++) {
         printf("  %s\n", earop.out.priv_names[j]);
      }

      printf("\n");


      i++;
   }

   /*if we want a partial success to occur below, then add the server's SIDs to the end of the array*/
   if(sim_partial) {
      sid_buf[i] = fsop.out.local_sid->sid;
      sid_buf[i+1] = fsop.out.domain_sid->sid;
   }

   fprintf(stdout, "Looking up Names from SIDs\n");

   struct LsaGetNamesFromSids gnop;
   ZERO_STRUCT(gnop);

   gnop.in.pol       = lsa_pol;
   gnop.in.num_sids  = num_sids;
   gnop.in.sids      = sid_buf;

   result = cac_LsaGetNamesFromSids(hnd, mem_ctx, &gnop);

   if(!result) {
      fprintf(stderr, "Could not lookup any names!.\n Error: %s\n", nt_errstr(hnd->status));
      goto done;
   }

   if(result == CAC_PARTIAL_SUCCESS) {
      fprintf(stdout, "\nNot all SIDs could be looked up.\n. The following SIDs were not found:\n");

      for(i = 0; i < (num_sids - gnop.out.num_found); i++) {
         fprintf(stdout, "SID: %s\n", sid_string_static(&gnop.out.unknown[i]));
      }

      fprintf(stdout, "\n");
   }

   fprintf(stdout, "%d SIDs were resolved: \n", gnop.out.num_found);
   for(i = 0; i < gnop.out.num_found; i++) {
      fprintf(stdout, " SID: %s\n Name: %s\n", sid_string_static(&gnop.out.sids[i].sid), gsop.out.sids[i].name);
   }
   
done:

   if(!cac_LsaClosePolicy(hnd, mem_ctx, lsa_pol)) {
      fprintf(stderr, "Could not close LSA policy handle.\n Error: %s\n", nt_errstr(hnd->status));
   }
   else {
      fprintf(stdout, "Closed Policy handle.\n");
   }

   cac_FreeHandle(hnd);
   talloc_destroy(mem_ctx);

   return 0;
}
Beispiel #20
0
static connection_struct *make_connection_snum(int snum, user_struct *vuser,
					       DATA_BLOB password, 
					       const char *pdev,
					       NTSTATUS *status)
{
	struct passwd *pass = NULL;
	BOOL guest = False;
	connection_struct *conn;
	SMB_STRUCT_STAT st;
	fstring user;
	fstring dev;
	int ret;
	struct timespec atime_ts, mtime_ts, ctime_ts;

	*user = 0;
	fstrcpy(dev, pdev);
	SET_STAT_INVALID(st);

	if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
		return NULL;
	}	

	conn = conn_new();
	if (!conn) {
		DEBUG(0,("Couldn't find free connection.\n"));
		*status = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}

	conn->params->service = snum;
	conn->nt_user_token = NULL;

	if (lp_guest_only(snum)) {
		const char *guestname = lp_guestaccount();
		NTSTATUS status2;
		char *found_username = NULL;

		guest = True;
		pass = getpwnam_alloc(NULL, guestname);
		if (!pass) {
			DEBUG(0,("make_connection_snum: Invalid guest "
				 "account %s??\n",guestname));
			conn_free(conn);
			*status = NT_STATUS_NO_SUCH_USER;
			return NULL;
		}
		status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
						     &conn->uid, &conn->gid,
						     &found_username,
						     &conn->nt_user_token);
		if (!NT_STATUS_IS_OK(status2)) {
			TALLOC_FREE(pass);
			conn_free(conn);
			*status = status2;
			return NULL;
		}
		fstrcpy(user, found_username);
		string_set(&conn->user,user);
		conn->force_user = True;
		TALLOC_FREE(found_username);
		TALLOC_FREE(pass);
		DEBUG(3,("Guest only user %s\n",user));
	} else if (vuser) {
		if (vuser->guest) {
			if (!lp_guest_ok(snum)) {
				DEBUG(2, ("guest user (from session setup) "
					  "not permitted to access this share "
					  "(%s)\n", lp_servicename(snum)));
				      conn_free(conn);
				      *status = NT_STATUS_ACCESS_DENIED;
				      return NULL;
			}
		} else {
			if (!user_ok_token(vuser->user.unix_name,
					   vuser->nt_user_token, snum)) {
				DEBUG(2, ("user '%s' (from session setup) not "
					  "permitted to access this share "
					  "(%s)\n", vuser->user.unix_name,
					  lp_servicename(snum)));
				conn_free(conn);
				*status = NT_STATUS_ACCESS_DENIED;
				return NULL;
			}
		}
		conn->vuid = vuser->vuid;
		conn->uid = vuser->uid;
		conn->gid = vuser->gid;
		string_set(&conn->user,vuser->user.unix_name);
		fstrcpy(user,vuser->user.unix_name);
		guest = vuser->guest; 
	} else if (lp_security() == SEC_SHARE) {
		NTSTATUS status2;
		char *found_username = NULL;

		/* add it as a possible user name if we 
		   are in share mode security */
		add_session_user(lp_servicename(snum));
		/* shall we let them in? */
		if (!authorise_login(snum,user,password,&guest)) {
			DEBUG( 2, ( "Invalid username/password for [%s]\n", 
				    lp_servicename(snum)) );
			conn_free(conn);
			*status = NT_STATUS_WRONG_PASSWORD;
			return NULL;
		}
		pass = Get_Pwnam(user);
		status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
						     &conn->uid, &conn->gid,
						     &found_username,
						     &conn->nt_user_token);
		if (!NT_STATUS_IS_OK(status2)) {
			conn_free(conn);
			*status = status2;
			return NULL;
		}
		fstrcpy(user, found_username);
		string_set(&conn->user,user);
		TALLOC_FREE(found_username);
		conn->force_user = True;
	} else {
		DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
		conn_free(conn);
		*status = NT_STATUS_ACCESS_DENIED;
		return NULL;
	}

	add_session_user(user);

	safe_strcpy(conn->client_address, client_addr(), 
		    sizeof(conn->client_address)-1);
	conn->num_files_open = 0;
	conn->lastused = conn->lastused_count = time(NULL);
	conn->used = True;
	conn->printer = (strncmp(dev,"LPT",3) == 0);
	conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
		      ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
	conn->dirptr = NULL;

	/* Case options for the share. */
	if (lp_casesensitive(snum) == Auto) {
		/* We will be setting this per packet. Set to be case
		 * insensitive for now. */
		conn->case_sensitive = False;
	} else {
		conn->case_sensitive = (BOOL)lp_casesensitive(snum);
	}

	conn->case_preserve = lp_preservecase(snum);
	conn->short_case_preserve = lp_shortpreservecase(snum);

	conn->veto_list = NULL;
	conn->hide_list = NULL;
	conn->veto_oplock_list = NULL;
	conn->aio_write_behind_list = NULL;
	string_set(&conn->dirpath,"");
	string_set(&conn->user,user);

	conn->read_only = lp_readonly(SNUM(conn));
	conn->admin_user = False;

	/*
	 * If force user is true, then store the given userid and the gid of
	 * the user we're forcing.
	 * For auxiliary groups see below.
	 */
	
	if (*lp_force_user(snum)) {
		NTSTATUS status2;

		status2 = find_forced_user(conn,
				(vuser != NULL) && vuser->guest,
				user);
		if (!NT_STATUS_IS_OK(status2)) {
			conn_free(conn);
			*status = status2;
			return NULL;
		}
		string_set(&conn->user,user);
		conn->force_user = True;
		DEBUG(3,("Forced user %s\n",user));	  
	}

	/*
	 * If force group is true, then override
	 * any groupid stored for the connecting user.
	 */
	
	if (*lp_force_group(snum)) {
		NTSTATUS status2;
		DOM_SID group_sid;

		status2 = find_forced_group(conn->force_user,
					    snum, user,
					    &group_sid, &conn->gid);
		if (!NT_STATUS_IS_OK(status2)) {
			conn_free(conn);
			*status = status2;
			return NULL;
		}

		if ((conn->nt_user_token == NULL) && (vuser != NULL)) {

			/* Not force user and not security=share, but force
			 * group. vuser has a token to copy */
			
			conn->nt_user_token = dup_nt_token(
				NULL, vuser->nt_user_token);
			if (conn->nt_user_token == NULL) {
				DEBUG(0, ("dup_nt_token failed\n"));
				conn_free(conn);
				*status = NT_STATUS_NO_MEMORY;
				return NULL;
			}
		}

		/* If conn->nt_user_token is still NULL, we have
		 * security=share. This means ignore the SID, as we had no
		 * vuser to copy from */

		if (conn->nt_user_token != NULL) {
			/* Overwrite the primary group sid */
			sid_copy(&conn->nt_user_token->user_sids[1],
				 &group_sid);

		}
		conn->force_group = True;
	}

	if (conn->nt_user_token != NULL) {
		size_t i;

		/* We have a share-specific token from force [user|group].
		 * This means we have to create the list of unix groups from
		 * the list of sids. */

		conn->ngroups = 0;
		conn->groups = NULL;

		for (i=0; i<conn->nt_user_token->num_sids; i++) {
			gid_t gid;
			DOM_SID *sid = &conn->nt_user_token->user_sids[i];

			if (!sid_to_gid(sid, &gid)) {
				DEBUG(10, ("Could not convert SID %s to gid, "
					   "ignoring it\n",
					   sid_string_static(sid)));
				continue;
			}
			if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
						&conn->ngroups)) {
				DEBUG(0, ("add_gid_to_array_unique failed\n"));
				conn_free(conn);
				*status = NT_STATUS_NO_MEMORY;
				return NULL;
			}
		}
	}

	{
		pstring s;
		pstrcpy(s,lp_pathname(snum));
		standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
				      conn->connectpath, conn->gid,
				      get_current_username(),
				      current_user_info.domain,
				      s, sizeof(s));

		if (s[0] == '\0') {
			DEBUG(6, ("service [%s] did not resolve to a path\n",
				lp_servicename(snum)));
			conn_free(conn);
			*status = NT_STATUS_BAD_NETWORK_NAME;
			return NULL;
		}

		set_conn_connectpath(conn,s);
		DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
			 lp_servicename(snum)));
	}

	/*
	 * New code to check if there's a share security descripter
	 * added from NT server manager. This is done after the
	 * smb.conf checks are done as we need a uid and token. JRA.
	 *
	 */

	{
		BOOL can_write = False;
		NT_USER_TOKEN *token = conn->nt_user_token ?
			conn->nt_user_token :
			(vuser ? vuser->nt_user_token : NULL);

		/*
		 * I don't believe this can happen. But the
		 * logic above is convoluted enough to confuse
		 * automated checkers, so be sure. JRA.
		 */

		if (token == NULL) {
			DEBUG(0,("make_connection: connection to %s "
				 "denied due to missing "
				 "NT token.\n",
				  lp_servicename(snum)));
			conn_free(conn);
			*status = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}

		can_write = share_access_check(token,
						    lp_servicename(snum),
						    FILE_WRITE_DATA);

		if (!can_write) {
			if (!share_access_check(token,
						lp_servicename(snum),
						FILE_READ_DATA)) {
				/* No access, read or write. */
				DEBUG(0,("make_connection: connection to %s "
					 "denied due to security "
					 "descriptor.\n",
					  lp_servicename(snum)));
				conn_free(conn);
				*status = NT_STATUS_ACCESS_DENIED;
				return NULL;
			} else {
				conn->read_only = True;
			}
		}
	}
	/* Initialise VFS function pointers */

	if (!smbd_vfs_init(conn)) {
		DEBUG(0, ("vfs_init failed for service %s\n",
			  lp_servicename(snum)));
		conn_free(conn);
		*status = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

	/*
	 * If widelinks are disallowed we need to canonicalise the connect
	 * path here to ensure we don't have any symlinks in the
	 * connectpath. We will be checking all paths on this connection are
	 * below this directory. We must do this after the VFS init as we
	 * depend on the realpath() pointer in the vfs table. JRA.
	 */
	if (!lp_widelinks(snum)) {
		pstring s;
		pstrcpy(s,conn->connectpath);
		canonicalize_path(conn, s);
		set_conn_connectpath(conn,s);
	}

	if ((!conn->printer) && (!conn->ipc)) {
		conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
					       smbd_messaging_context(),
					       smbd_event_context(),
					       conn);
	}

/* ROOT Activities: */	
	/* check number of connections */
	if (!claim_connection(conn,
			      lp_servicename(snum),
			      lp_max_connections(snum),
			      False,0)) {
		DEBUG(1,("too many connections - rejected\n"));
		conn_free(conn);
		*status = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}  

	/* Preexecs are done here as they might make the dir we are to ChDir
	 * to below */
	/* execute any "root preexec = " line */
	if (*lp_rootpreexec(snum)) {
		pstring cmd;
		pstrcpy(cmd,lp_rootpreexec(snum));
		standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
				      conn->connectpath, conn->gid,
				      get_current_username(),
				      current_user_info.domain,
				      cmd, sizeof(cmd));
		DEBUG(5,("cmd=%s\n",cmd));
		ret = smbrun(cmd,NULL);
		if (ret != 0 && lp_rootpreexec_close(snum)) {
			DEBUG(1,("root preexec gave %d - failing "
				 "connection\n", ret));
			yield_connection(conn, lp_servicename(snum));
			conn_free(conn);
			*status = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}
	}

/* USER Activites: */
	if (!change_to_user(conn, conn->vuid)) {
		/* No point continuing if they fail the basic checks */
		DEBUG(0,("Can't become connected user!\n"));
		yield_connection(conn, lp_servicename(snum));
		conn_free(conn);
		*status = NT_STATUS_LOGON_FAILURE;
		return NULL;
	}

	/* Remember that a different vuid can connect later without these
	 * checks... */
	
	/* Preexecs are done here as they might make the dir we are to ChDir
	 * to below */

	/* execute any "preexec = " line */
	if (*lp_preexec(snum)) {
		pstring cmd;
		pstrcpy(cmd,lp_preexec(snum));
		standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
				      conn->connectpath, conn->gid,
				      get_current_username(),
				      current_user_info.domain,
				      cmd, sizeof(cmd));
		ret = smbrun(cmd,NULL);
		if (ret != 0 && lp_preexec_close(snum)) {
			DEBUG(1,("preexec gave %d - failing connection\n",
				 ret));
			change_to_root_user();
			yield_connection(conn, lp_servicename(snum));
			conn_free(conn);
			*status = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}
	}

#ifdef WITH_FAKE_KASERVER
	if (lp_afs_share(snum)) {
		afs_login(conn);
	}
#endif
	
	/* Add veto/hide lists */
	if (!IS_IPC(conn) && !IS_PRINT(conn)) {
		set_namearray( &conn->veto_list, lp_veto_files(snum));
		set_namearray( &conn->hide_list, lp_hide_files(snum));
		set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
	}
	
	/* Invoke VFS make connection hook - do this before the VFS_STAT call
	   to allow any filesystems needing user credentials to initialize
	   themselves. */

	if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
		DEBUG(0,("make_connection: VFS make connection failed!\n"));
		change_to_root_user();
		yield_connection(conn, lp_servicename(snum));
		conn_free(conn);
		*status = NT_STATUS_UNSUCCESSFUL;
		return NULL;
	}

	/* win2000 does not check the permissions on the directory
	   during the tree connect, instead relying on permission
	   check during individual operations. To match this behaviour
	   I have disabled this chdir check (tridge) */
	/* the alternative is just to check the directory exists */
	if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
	    !S_ISDIR(st.st_mode)) {
		if (ret == 0 && !S_ISDIR(st.st_mode)) {
			DEBUG(0,("'%s' is not a directory, when connecting to "
				 "[%s]\n", conn->connectpath,
				 lp_servicename(snum)));
		} else {
			DEBUG(0,("'%s' does not exist or permission denied "
				 "when connecting to [%s] Error was %s\n",
				 conn->connectpath, lp_servicename(snum),
				 strerror(errno) ));
		}
		change_to_root_user();
		/* Call VFS disconnect hook */    
		SMB_VFS_DISCONNECT(conn);
		yield_connection(conn, lp_servicename(snum));
		conn_free(conn);
		*status = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

	string_set(&conn->origpath,conn->connectpath);

	mtime_ts = get_mtimespec(&st);
	ctime_ts = get_ctimespec(&st);
	atime_ts = get_atimespec(&st);

	conn->ts_res = TIMESTAMP_SET_SECONDS;

	if (mtime_ts.tv_nsec ||
			atime_ts.tv_nsec ||
			ctime_ts.tv_nsec) {
		/* If any of the normal UNIX directory timestamps
		 * have a non-zero tv_nsec component assume
		 * we might be able to set sub-second timestamps.
		 * See what filetime set primitives we have.
		 */
#if defined(HAVE_UTIMES)
		/* utimes allows msec timestamps to be set. */
		conn->ts_res = TIMESTAMP_SET_MSEC;
#elif defined(HAVE_UTIME)
		/* utime only allows sec timestamps to be set. */
		conn->ts_res = TIMESTAMP_SET_SECONDS;
#endif

		/* TODO. Add a configure test for the Linux
		 * nsec timestamp set system call, and use it
		 * if available....
		 */
		DEBUG(10,("make_connection_snum: timestamp "
			"resolution of %s "
			"available on share %s, directory %s\n",
			conn->ts_res == TIMESTAMP_SET_MSEC ? "msec" : "sec",
			lp_servicename(conn->cnum),
			conn->connectpath ));
	}

#if SOFTLINK_OPTIMISATION
	/* resolve any soft links early if possible */
	if (vfs_ChDir(conn,conn->connectpath) == 0) {
		pstring s;
		pstrcpy(s,conn->connectpath);
		vfs_GetWd(conn,s);
		set_conn_connectpath(conn,s);
		vfs_ChDir(conn,conn->connectpath);
	}
#endif
	
	if (lp_unix_extensions() && lp_widelinks(snum)) {
		DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
			"These parameters are incompatible. "
			"Disabling wide links for this share.\n",
			lp_servicename(snum) ));
		lp_do_parameter(snum, "wide links", "False");
	}

	/*
	 * Print out the 'connected as' stuff here as we need
	 * to know the effective uid and gid we will be using
	 * (at least initially).
	 */

	if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
		dbgtext( "%s (%s) ", get_remote_machine_name(),
			 conn->client_address );
		dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
		dbgtext( "connect to service %s ", lp_servicename(snum) );
		dbgtext( "initially as user %s ", user );
		dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
		dbgtext( "(pid %d)\n", (int)sys_getpid() );
	}
	
	/* we've finished with the user stuff - go back to root */
	change_to_root_user();
	return(conn);
}
Beispiel #21
0
static NTSTATUS find_forced_group(BOOL force_user,
				  int snum, const char *username,
				  DOM_SID *pgroup_sid,
				  gid_t *pgid)
{
	NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
	TALLOC_CTX *mem_ctx;
	DOM_SID group_sid;
	enum lsa_SidType type;
	char *groupname;
	BOOL user_must_be_member = False;
	gid_t gid;

	ZERO_STRUCTP(pgroup_sid);
	*pgid = (gid_t)-1;

	mem_ctx = talloc_new(NULL);
	if (mem_ctx == NULL) {
		DEBUG(0, ("talloc_new failed\n"));
		return NT_STATUS_NO_MEMORY;
	}

	groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
	if (groupname == NULL) {
		DEBUG(1, ("talloc_strdup failed\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	if (groupname[0] == '+') {
		user_must_be_member = True;
		groupname += 1;
	}

	groupname = talloc_string_sub(mem_ctx, groupname,
				      "%S", lp_servicename(snum));

	if (!lookup_name_smbconf(mem_ctx, groupname,
			 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
			 NULL, NULL, &group_sid, &type)) {
		DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
			   groupname));
		goto done;
	}

	if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
	    (type != SID_NAME_WKN_GRP)) {
		DEBUG(10, ("%s is a %s, not a group\n", groupname,
			   sid_type_lookup(type)));
		goto done;
	}

	if (!sid_to_gid(&group_sid, &gid)) {
		DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
			   sid_string_static(&group_sid), groupname));
		goto done;
	}

	/*
	 * If the user has been forced and the forced group starts with a '+',
	 * then we only set the group to be the forced group if the forced
	 * user is a member of that group.  Otherwise, the meaning of the '+'
	 * would be ignored.
	 */

	if (force_user && user_must_be_member) {
		if (user_in_group_sid(username, &group_sid)) {
			sid_copy(pgroup_sid, &group_sid);
			*pgid = gid;
			DEBUG(3,("Forced group %s for member %s\n",
				 groupname, username));
		} else {
			DEBUG(0,("find_forced_group: forced user %s is not a member "
				"of forced group %s. Disallowing access.\n",
				username, groupname ));
			result = NT_STATUS_MEMBER_NOT_IN_GROUP;
			goto done;
		}
	} else {
		sid_copy(pgroup_sid, &group_sid);
		*pgid = gid;
		DEBUG(3,("Forced group %s\n", groupname));
	}

	result = NT_STATUS_OK;
 done:
	TALLOC_FREE(mem_ctx);
	return result;
}
Beispiel #22
0
/* Lookup user information from a rid or username. */
static NTSTATUS query_user(struct winbindd_domain *domain, 
			   TALLOC_CTX *mem_ctx, 
			   const DOM_SID *user_sid, 
			   WINBIND_USERINFO *user_info)
{
	CLI_POLICY_HND *hnd = NULL;
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	POLICY_HND dom_pol, user_pol;
	BOOL got_dom_pol = False, got_user_pol = False;
	SAM_USERINFO_CTR *ctr;
	int retry;
	fstring sid_string;
	uint32 user_rid;
	NET_USER_INFO_3 *user;

	DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid)));
	if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
		goto done;
	}
	
	/* try netsamlogon cache first */
			
	if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) 
	{
				
		DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
			sid_string_static(user_sid)));
			
		user_info->user_sid  = rid_to_talloced_sid( domain, mem_ctx, user_rid );
		user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid );
				
		user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name);
		user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name);
								
		SAFE_FREE(user);
				
		return NT_STATUS_OK;
	}
	
	/* no cache; hit the wire */
		
	retry = 0;
	do {
		/* Get sam handle; if we fail here there is no hope */
		
		if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) 
			goto done;
			
		/* Get domain handle */

		result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
					      SEC_RIGHTS_MAXIMUM_ALLOWED, 
					      &domain->sid, &dom_pol);
	} while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&
			hnd && hnd->cli && hnd->cli->fd == -1);

	if (!NT_STATUS_IS_OK(result))
		goto done;

	got_dom_pol = True;

	/* Get user handle */
	result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
				    SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);

	if (!NT_STATUS_IS_OK(result))
		goto done;

	got_user_pol = True;

	/* Get user info */
	result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol, 
					 0x15, &ctr);

	if (!NT_STATUS_IS_OK(result))
		goto done;

	cli_samr_close(hnd->cli, mem_ctx, &user_pol);
	got_user_pol = False;

	user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid);
	user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid);
	user_info->acct_name = unistr2_tdup(mem_ctx, 
					    &ctr->info.id21->uni_user_name);
	user_info->full_name = unistr2_tdup(mem_ctx, 
					    &ctr->info.id21->uni_full_name);

 done:
	/* Clean up policy handles */
	if (got_user_pol)
		cli_samr_close(hnd->cli, mem_ctx, &user_pol);

	if (got_dom_pol)
		cli_samr_close(hnd->cli, mem_ctx, &dom_pol);

	return result;
}                                   
Beispiel #23
0
static BOOL nt_to_afs_acl(const char *filename,
			  uint32 security_info_sent,
			  struct security_descriptor *psd,
			  uint32 (*nt_to_afs_rights)(const char *filename,
						     const SEC_ACE *ace),
			  struct afs_acl *afs_acl)
{
	SEC_ACL *dacl;
	int i;

	/* Currently we *only* look at the dacl */

	if (((security_info_sent & DACL_SECURITY_INFORMATION) == 0) ||
	    (psd->dacl == NULL))
		return True;

	if (!init_afs_acl(afs_acl))
		return False;

	dacl = psd->dacl;

	for (i = 0; i < dacl->num_aces; i++) {
		SEC_ACE *ace = &(dacl->ace[i]);
		const char *dom_name, *name;
		enum lsa_SidType name_type;
		char *p;

		if (ace->type != SEC_ACE_TYPE_ACCESS_ALLOWED) {
			/* First cut: Only positive ACEs */
			return False;
		}

		if (!mappable_sid(&ace->trustee)) {
			DEBUG(10, ("Ignoring unmappable SID %s\n",
				   sid_string_static(&ace->trustee)));
			continue;
		}

		if (sid_compare(&ace->trustee,
				&global_sid_Builtin_Administrators) == 0) {

			name = "system:administrators";

		} else if (sid_compare(&ace->trustee,
				       &global_sid_World) == 0) {

			name = "system:anyuser";

		} else if (sid_compare(&ace->trustee,
				       &global_sid_Authenticated_Users) == 0) {

			name = "system:authuser";

		} else if (sid_compare(&ace->trustee,
				       &global_sid_Builtin_Backup_Operators)
			   == 0) {

			name = "system:backup";

		} else {

			if (!lookup_sid(tmp_talloc_ctx(), &ace->trustee,
					&dom_name, &name, &name_type)) {
				DEBUG(1, ("AFSACL: Could not lookup SID %s on file %s\n",
					  sid_string_static(&ace->trustee), filename));
				continue;
			}

			if ( (name_type == SID_NAME_USER) ||
			     (name_type == SID_NAME_DOM_GRP) ||
			     (name_type == SID_NAME_ALIAS) ) {
				char *tmp;
				tmp = talloc_asprintf(tmp_talloc_ctx(), "%s%s%s",
						       dom_name, lp_winbind_separator(),
						       name);
				if (tmp == NULL) {
					return False;
				}
				strlower_m(tmp);
				name = tmp;
			}

			if (sidpts) {
				/* Expect all users/groups in pts as SIDs */
				name = talloc_strdup(
					tmp_talloc_ctx(),
					sid_string_static(&ace->trustee));
				if (name == NULL) {
					return False;
				}
			}
		}

		while ((p = strchr_m(name, ' ')) != NULL)
			*p = space_replacement;

		add_afs_ace(afs_acl, True, name,
			    nt_to_afs_rights(filename, ace));
	}

	return True;
}
Beispiel #24
0
int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
{
	struct passwd *usr;
	TALLOC_CTX *mem_ctx = NULL;

	if (!fsp||!fsp->conn||!qt_list)
		return (-1);

	*qt_list = NULL;

	if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) {
		DEBUG(0,("talloc_init() failed\n"));
		return (-1);
	}

	sys_setpwent();
	while ((usr = sys_getpwent()) != NULL) {
		SMB_NTQUOTA_STRUCT tmp_qt;
		SMB_NTQUOTA_LIST *tmp_list_ent;
		DOM_SID	sid;

		ZERO_STRUCT(tmp_qt);

		if (allready_in_quota_list((*qt_list),usr->pw_uid)) {
			DEBUG(5,("record for uid[%ld] allready in the list\n",(long)usr->pw_uid));
			continue;
		}

		uid_to_sid(&sid, usr->pw_uid);

		if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) {
			DEBUG(5,("no quota entry for sid[%s] path[%s]\n",
				sid_string_static(&sid),fsp->conn->connectpath));
			continue;
		}

		DEBUG(15,("quota entry for id[%s] path[%s]\n",
			sid_string_static(&sid),fsp->conn->connectpath));

		if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
			DEBUG(0,("TALLOC_ZERO() failed\n"));
			*qt_list = NULL;
			talloc_destroy(mem_ctx);
			return (-1);
		}

		if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
			DEBUG(0,("TALLOC_ZERO() failed\n"));
			*qt_list = NULL;
			talloc_destroy(mem_ctx);
			return (-1);
		}

		tmp_list_ent->uid = usr->pw_uid;
		memcpy(tmp_list_ent->quotas,&tmp_qt,sizeof(tmp_qt));
		tmp_list_ent->mem_ctx = mem_ctx;

		DLIST_ADD((*qt_list),tmp_list_ent);
		
	}
	sys_endpwent();

	return 0;
}
Beispiel #25
0
/* Lookup groups a user is a member of.  I wish Unix had a call like this! */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
				  TALLOC_CTX *mem_ctx,
				  const DOM_SID *user_sid,
				  uint32 *num_groups, DOM_SID ***user_grpsids)
{
	CLI_POLICY_HND *hnd;
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	POLICY_HND dom_pol, user_pol;
	uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
	BOOL got_dom_pol = False, got_user_pol = False;
	DOM_GID *user_groups;
	unsigned int i;
	unsigned int retry;
	fstring sid_string;
	uint32 user_rid;
	NET_USER_INFO_3 *user;

	DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid)));

	*num_groups = 0;
	*user_grpsids = NULL;

	/* so lets see if we have a cached user_info_3 */
	
	if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL )
	{
		DEBUG(5,("query_user: Cache lookup succeeded for %s\n", 
			sid_string_static(user_sid)));
			
		*num_groups = user->num_groups;
				
		(*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups));
		for (i=0;i<(*num_groups);i++) {
			(*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid);
		}
				
		SAFE_FREE(user);
				
		return NT_STATUS_OK;
	}

	/* no cache; hit the wire */
	
	retry = 0;
	do {
		/* Get sam handle; if we fail here there is no hope */
		
		if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) 		
			goto done;

		/* Get domain handle */
		
		result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol,
					      des_access, &domain->sid, &dom_pol);
	} while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && 
			hnd && hnd->cli && hnd->cli->fd == -1);

	if (!NT_STATUS_IS_OK(result))
		goto done;

	got_dom_pol = True;


	if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
		goto done;
	}

	/* Get user handle */
	result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol,
					des_access, user_rid, &user_pol);

	if (!NT_STATUS_IS_OK(result))
		goto done;

	got_user_pol = True;

	/* Query user rids */
	result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol, 
					   num_groups, &user_groups);

	if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0)
		goto done;

	(*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups));
	if (!(*user_grpsids)) {
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	for (i=0;i<(*num_groups);i++) {
		(*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid);
	}
	
 done:
	/* Clean up policy handles */
	if (got_user_pol)
		cli_samr_close(hnd->cli, mem_ctx, &user_pol);

	if (got_dom_pol)
		cli_samr_close(hnd->cli, mem_ctx, &dom_pol);

	return result;
}
Beispiel #26
0
enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
							struct winbindd_cli_state *state)
{
	uint32 i, num_domains;
	char **names, **alt_names;
	DOM_SID *sids;
	int extra_data_len = 0;
	char *extra_data;
	NTSTATUS result;
	BOOL have_own_domain = False;

	DEBUG(3, ("[%5lu]: list trusted domains\n",
		  (unsigned long)state->pid));

	result = domain->methods->trusted_domains(domain, state->mem_ctx,
						  &num_domains, &names,
						  &alt_names, &sids);

	if (!NT_STATUS_IS_OK(result)) {
		DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
			nt_errstr(result) ));
		return WINBINDD_ERROR;
	}

	extra_data = talloc_strdup(state->mem_ctx, "");

	if (num_domains > 0)
		extra_data = talloc_asprintf(state->mem_ctx, "%s\\%s\\%s",
					     names[0],
					     alt_names[0] ? alt_names[0] : names[0],
					     sid_string_static(&sids[0]));

	for (i=1; i<num_domains; i++)
		extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
					     extra_data,
					     names[i],
					     alt_names[i] ? alt_names[i] : names[i],
					     sid_string_static(&sids[i]));
	/* add our primary domain */
	
	for (i=0; i<num_domains; i++) {
		if (strequal(names[i], domain->name)) {
			have_own_domain = True;
			break;
		}
	}

	if (state->request.data.list_all_domains && !have_own_domain) {
		extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
					     extra_data,
					     domain->name,
					     domain->alt_name ? domain->alt_name : domain->name,
					     sid_string_static(&domain->sid));
	}

	/* This is a bit excessive, but the extra data sooner or later will be
	   talloc'ed */

	extra_data_len = 0;
	if (extra_data != NULL) {
		extra_data_len = strlen(extra_data);
	}

	if (extra_data_len > 0) {
		state->response.extra_data.data = SMB_STRDUP(extra_data);
		state->response.length += extra_data_len+1;
	}

	return WINBINDD_OK;
}