Ejemplo n.º 1
0
static int register_homes_share(const char *username)
{
	int result;
	struct passwd *pwd;

	result = lp_servicenumber(username);
	if (result != -1) {
		DEBUG(3, ("Using static (or previously created) service for "
			  "user '%s'; path = '%s'\n", username,
			  lp_pathname(result)));
		return result;
	}

	pwd = getpwnam_alloc(talloc_tos(), username);

	if ((pwd == NULL) || (pwd->pw_dir[0] == '\0')) {
		DEBUG(3, ("No home directory defined for user '%s'\n",
			  username));
		TALLOC_FREE(pwd);
		return -1;
	}

	DEBUG(3, ("Adding homes service for user '%s' using home directory: "
		  "'%s'\n", username, pwd->pw_dir));

	result = add_home_service(username, username, pwd->pw_dir);

	TALLOC_FREE(pwd);
	return result;
}
Ejemplo n.º 2
0
/***************************************************************************
authenticate when we are running as a CGI
  ***************************************************************************/
static void cgi_web_auth(void)
{
	const char *user = getenv("REMOTE_USER");
	struct passwd *pwd;
	const char *head = "Content-Type: text/html\r\n\r\n<HTML><BODY><H1>SWAT installation Error</H1>\n";
	const char *tail = "</BODY></HTML>\r\n";

	if (!user) {
		printf("%sREMOTE_USER not set. Not authenticated by web server.<br>%s\n",
		       head, tail);
		exit(0);
	}

	pwd = getpwnam_alloc(talloc_autofree_context(), user);
	if (!pwd) {
		printf("%sCannot find user %s<br>%s\n", head, user, tail);
		exit(0);
	}

	setuid(0);
	setuid(pwd->pw_uid);
	if (geteuid() != pwd->pw_uid || getuid() != pwd->pw_uid) {
		printf("%sFailed to become user %s - uid=%d/%d<br>%s\n", 
		       head, user, (int)geteuid(), (int)getuid(), tail);
		exit(0);
	}
	TALLOC_FREE(pwd);
}
Ejemplo n.º 3
0
BOOL change_to_guest(void)
{
	static struct passwd *pass=NULL;

	if (!pass) {
		/* Don't need to free() this as its stored in a static */
		pass = getpwnam_alloc(lp_guestaccount());
		if (!pass)
			return(False);
	}
	
#ifdef AIX
	/* MWW: From AIX FAQ patch to WU-ftpd: call initgroups before 
	   setting IDs */
	initgroups(pass->pw_name, pass->pw_gid);
#endif
	
	set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
	
	current_user.conn = NULL;
	current_user.vuid = UID_FIELD_INVALID;
	
	passwd_free(&pass);

	return True;
}
Ejemplo n.º 4
0
static gint
get_user_groups (ActUser *user,
                 gid_t *primary,
                 gid_t **groups)
{
    struct passwd *pwd;
    const gchar *name;
    gint res;
    gint ngroups;

    name = act_user_get_user_name (user);
    pwd = getpwnam_alloc (name);
    if (pwd == NULL)
    {
        *primary = -1;
        *groups = NULL;
        return 0;
    }

    *primary = pwd->pw_gid;

    ngroups = 0;
    res = getgrouplist (name, *primary, NULL, &ngroups);

    g_debug ("user %s has %d groups", name, ngroups);
    *groups = g_new (gid_t, ngroups);
    res = getgrouplist (name, *primary, *groups, &ngroups);

    g_free (pwd);
    return res;
}
Ejemplo n.º 5
0
bool lookup_unix_user_name(const char *name, DOM_SID *sid)
{
	struct passwd *pwd;
	bool ret;

	pwd = getpwnam_alloc(talloc_autofree_context(), name);
	if (pwd == NULL) {
		return False;
	}

	/*
	 * For 64-bit uid's we have enough space in the whole SID,
	 * should they become necessary
	 */
	ret = sid_compose(sid, &global_sid_Unix_Users, pwd->pw_uid);
	TALLOC_FREE(pwd);
	return ret;
}
Ejemplo n.º 6
0
int register_vuid(auth_serversupplied_info *server_info,
		  DATA_BLOB session_key, DATA_BLOB response_blob,
		  const char *smb_name)
{
	user_struct *vuser = NULL;

	/* Paranoia check. */
	if(lp_security() == SEC_SHARE) {
		smb_panic("Tried to register uid in security=share\n");
	}

	/* Limit allowed vuids to 16bits - VUID_OFFSET. */
	if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
		data_blob_free(&session_key);
		return UID_FIELD_INVALID;
	}

	if((vuser = SMB_MALLOC_P(user_struct)) == NULL) {
		DEBUG(0,("Failed to malloc users struct!\n"));
		data_blob_free(&session_key);
		return UID_FIELD_INVALID;
	}

	ZERO_STRUCTP(vuser);

	/* Allocate a free vuid. Yes this is a linear search... :-) */
	while( get_valid_user_struct(next_vuid) != NULL ) {
		next_vuid++;
		/* Check for vuid wrap. */
		if (next_vuid == UID_FIELD_INVALID)
			next_vuid = VUID_OFFSET;
	}

	DEBUG(10,("register_vuid: allocated vuid = %u\n",
		  (unsigned int)next_vuid ));

	vuser->vuid = next_vuid;

	if (!server_info) {
		/*
		 * This happens in an unfinished NTLMSSP session setup. We
		 * need to allocate a vuid between the first and second calls
		 * to NTLMSSP.
		 */
		next_vuid++;
		num_validated_vuids++;
		
		vuser->server_info = NULL;
		
		DLIST_ADD(validated_users, vuser);
		
		return vuser->vuid;
	}

	/* the next functions should be done by a SID mapping system (SMS) as
	 * the new real sam db won't have reference to unix uids or gids
	 */
	
	vuser->uid = server_info->uid;
	vuser->gid = server_info->gid;
	
	vuser->n_groups = server_info->n_groups;
	if (vuser->n_groups) {
		if (!(vuser->groups = (gid_t *)memdup(server_info->groups,
						      sizeof(gid_t) *
						      vuser->n_groups))) {
			DEBUG(0,("register_vuid: failed to memdup "
				 "vuser->groups\n"));
			data_blob_free(&session_key);
			free(vuser);
			TALLOC_FREE(server_info);
			return UID_FIELD_INVALID;
		}
	}

	vuser->guest = server_info->guest;
	fstrcpy(vuser->user.unix_name, server_info->unix_name); 

	/* This is a potentially untrusted username */
	alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$",
		     sizeof(vuser->user.smb_name));

	fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
	fstrcpy(vuser->user.full_name,
		pdb_get_fullname(server_info->sam_account));

	{
		/* Keep the homedir handy */
		const char *homedir =
			pdb_get_homedir(server_info->sam_account);
		const char *logon_script =
			pdb_get_logon_script(server_info->sam_account);

		if (!IS_SAM_DEFAULT(server_info->sam_account,
				    PDB_UNIXHOMEDIR)) {
			const char *unix_homedir =
				pdb_get_unix_homedir(server_info->sam_account);
			if (unix_homedir) {
				vuser->unix_homedir =
					smb_xstrdup(unix_homedir);
			}
		} else {
			struct passwd *passwd =
				getpwnam_alloc(NULL, vuser->user.unix_name);
			if (passwd) {
				vuser->unix_homedir =
					smb_xstrdup(passwd->pw_dir);
				TALLOC_FREE(passwd);
			}
		}
		
		if (homedir) {
			vuser->homedir = smb_xstrdup(homedir);
		}
		if (logon_script) {
			vuser->logon_script = smb_xstrdup(logon_script);
		}
	}

	vuser->session_key = session_key;

	DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", 
		  (unsigned int)vuser->uid, 
		  (unsigned int)vuser->gid,
		  vuser->user.unix_name, vuser->user.smb_name,
		  vuser->user.domain, vuser->guest ));

	DEBUG(3, ("User name: %s\tReal name: %s\n", vuser->user.unix_name,
		  vuser->user.full_name));	

 	if (server_info->ptok) {
		vuser->nt_user_token = dup_nt_token(NULL, server_info->ptok);
	} else {
		DEBUG(1, ("server_info does not contain a user_token - "
			  "cannot continue\n"));
		TALLOC_FREE(server_info);
		data_blob_free(&session_key);
		SAFE_FREE(vuser->homedir);
		SAFE_FREE(vuser->unix_homedir);
		SAFE_FREE(vuser->logon_script);

		SAFE_FREE(vuser);
		return UID_FIELD_INVALID;
	}

	/* use this to keep tabs on all our info from the authentication */
	vuser->server_info = server_info;

	DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",
		 (int)vuser->uid,vuser->user.unix_name, vuser->vuid));

	next_vuid++;
	num_validated_vuids++;

	DLIST_ADD(validated_users, vuser);

	if (!session_claim(vuser)) {
		DEBUG(1, ("Failed to claim session for vuid=%d\n",
			  vuser->vuid));
		invalidate_vuid(vuser->vuid);
		return UID_FIELD_INVALID;
	}

	/* Register a home dir service for this user iff
	
	   (a) This is not a guest connection,
	   (b) we have a home directory defined 
	   (c) there s not an existing static share by that name
	   
	   If a share exists by this name (autoloaded or not) reuse it . */

	vuser->homes_snum = -1;

	if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) 
	{
		int servicenumber = lp_servicenumber(vuser->user.unix_name);

		if ( servicenumber == -1 ) {
			DEBUG(3, ("Adding homes service for user '%s' using "
				  "home directory: '%s'\n", 
				vuser->user.unix_name, vuser->unix_homedir));
			vuser->homes_snum =
				add_home_service(vuser->user.unix_name, 
						 vuser->user.unix_name,
						 vuser->unix_homedir);
		} else {
			DEBUG(3, ("Using static (or previously created) "
				  "service for user '%s'; path = '%s'\n", 
				  vuser->user.unix_name,
				  lp_pathname(servicenumber) ));
			vuser->homes_snum = servicenumber;
		}
	} 
	
	if (srv_is_signing_negotiated() && !vuser->guest &&
	    !srv_signing_started()) {
		/* Try and turn on server signing on the first non-guest
		 * sessionsetup. */
		srv_set_signing(vuser->session_key, response_blob);
	}
	
	/* fill in the current_user_info struct */
	set_current_user_info( &vuser->user );


	return vuser->vuid;
}
Ejemplo n.º 7
0
static int do_reseed(bool use_fd, int fd)
{
	unsigned char seed_inbuf[40];
	uint32 v1, v2; struct timeval tval; pid_t mypid;
	struct passwd *pw;
	int reseed_data = 0;

	if (use_fd) {
		if (fd != -1)
			return fd;

		fd = sys_open( "/dev/urandom", O_RDONLY,0);
		if(fd >= 0)
			return fd;
	}

	/* Add in some secret file contents */

	do_filehash("/etc/shadow", &seed_inbuf[0]);
	do_filehash(lp_smb_passwd_file(), &seed_inbuf[16]);

	/*
	 * Add in the root encrypted password.
	 * On any system where security is taken
	 * seriously this will be secret.
	 */

	pw = getpwnam_alloc(talloc_autofree_context(), "root");
	if (pw && pw->pw_passwd) {
		size_t i;
		unsigned char md4_tmp[16];
		mdfour(md4_tmp, (unsigned char *)pw->pw_passwd, strlen(pw->pw_passwd));
		for (i=0;i<16;i++)
			seed_inbuf[8+i] ^= md4_tmp[i];
		TALLOC_FREE(pw);
	}

	/*
	 * Add the counter, time of day, and pid.
	 */

	GetTimeOfDay(&tval);
	mypid = sys_getpid();
	v1 = (counter++) + mypid + tval.tv_sec;
	v2 = (counter++) * mypid + tval.tv_usec;

	SIVAL(seed_inbuf, 32, v1 ^ IVAL(seed_inbuf, 32));
	SIVAL(seed_inbuf, 36, v2 ^ IVAL(seed_inbuf, 36));

	/*
	 * Add any user-given reseed data.
	 */

	get_rand_reseed_data(&reseed_data);
	if (reseed_data) {
		size_t i;
		for (i = 0; i < sizeof(seed_inbuf); i++)
			seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)];
	}

	smb_arc4_init(smb_arc4_state, seed_inbuf, sizeof(seed_inbuf));

	return -1;
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
/***************************************************************************
handle a http authentication line
  ***************************************************************************/
static bool cgi_handle_authorization(char *line)
{
	char *p;
	fstring user, user_pass;
	struct passwd *pass = NULL;

	if (!strnequal(line,"Basic ", 6)) {
		goto err;
	}
	line += 6;
	while (line[0] == ' ') line++;
	base64_decode_inplace(line);
	if (!(p=strchr_m(line,':'))) {
		/*
		 * Always give the same error so a cracker
		 * cannot tell why we fail.
		 */
		goto err;
	}
	*p = 0;

	convert_string(CH_UTF8, CH_UNIX, 
		       line, -1, 
		       user, sizeof(user), True);

	convert_string(CH_UTF8, CH_UNIX, 
		       p+1, -1, 
		       user_pass, sizeof(user_pass), True);

	/*
	 * Try and get the user from the UNIX password file.
	 */
	
	pass = getpwnam_alloc(talloc_autofree_context(), user);
	
	/*
	 * Validate the password they have given.
	 */
	
	if NT_STATUS_IS_OK(pass_check(pass, user, user_pass, 
		      strlen(user_pass), NULL, False)) {
		
		if (pass) {
			/*
			 * Password was ok.
			 */
			
			if ( initgroups(pass->pw_name, pass->pw_gid) != 0 )
				goto err;

			become_user_permanently(pass->pw_uid, pass->pw_gid);
			
			/* Save the users name */
			C_user = SMB_STRDUP(user);
			TALLOC_FREE(pass);
			return True;
		}
	}
	
err:
	cgi_setup_error("401 Bad Authorization", 
			"WWW-Authenticate: Basic realm=\"SWAT\"\r\n",
			"username or password incorrect");

	TALLOC_FREE(pass);
	return False;
}
Ejemplo n.º 10
0
int main(int argc, char **argv)
{
	TALLOC_CTX *ctx;
	struct samu *out = NULL;
	struct samu *in = NULL;
	NTSTATUS rv;
	int i;
	struct timeval tv;
	BOOL error = False;
	struct passwd *pwd;
	uint8 *buf;
	uint32 expire, min_age, history;
	struct pdb_methods *pdb;
	poptContext pc;
	static const char *backend = NULL;
	static const char *unix_user = "******";
	struct poptOption long_options[] = {
		{"username", 'u', POPT_ARG_STRING, &unix_user, 0, "Unix user to use for testing", "USERNAME" },
		{"backend", 'b', POPT_ARG_STRING, &backend, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" },
		POPT_AUTOHELP
		POPT_COMMON_SAMBA
		POPT_TABLEEND
	};

	load_case_tables();

	pc = poptGetContext("vfstest", argc, (const char **) argv,
			    long_options, 0);

	poptSetOtherOptionHelp(pc, "backend[:settings] username");
	
	while(poptGetNextOpt(pc) != -1);

	poptFreeContext(pc);

	/* Load configuration */
	lp_load(dyn_CONFIGFILE, False, False, True, True);
	setup_logging("pdbtest", True);

	if (backend == NULL) {
		backend = lp_passdb_backend();
	}

	rv = make_pdb_method_name(&pdb, backend);
	if (NT_STATUS_IS_ERR(rv)) {
		fprintf(stderr, "Error initializing '%s': %s\n", backend, get_friendly_nt_error_msg(rv));
		exit(1);
	}
	
	ctx = talloc_init("PDBTEST");
	
	if (!(out = samu_new(ctx))) {
		fprintf(stderr, "Can't create samu structure.\n");
		exit(1);
	}
	
	if ((pwd = getpwnam_alloc(ctx, unix_user)) == NULL) {
		fprintf(stderr, "Error getting user information for %s\n", unix_user);
		exit(1);
	}
	
	samu_set_unix(out, pwd);

	pdb_set_profile_path(out, "\\\\torture\\profile", PDB_SET);
	pdb_set_homedir(out, "\\\\torture\\home", PDB_SET);
	pdb_set_logon_script(out, "torture_script.cmd", PDB_SET);

	pdb_get_account_policy(AP_PASSWORD_HISTORY, &history);
	if (history * PW_HISTORY_ENTRY_LEN < NT_HASH_LEN) {
		buf = (uint8 *)TALLOC(ctx, NT_HASH_LEN);
	} else {
		buf = (uint8 *)TALLOC(ctx, history * PW_HISTORY_ENTRY_LEN);
	}

	/* Generate some random hashes */
	GetTimeOfDay(&tv);
	srand(tv.tv_usec);
	for (i = 0; i < NT_HASH_LEN; i++) {
		buf[i] = (uint8) rand();
	}
	pdb_set_nt_passwd(out, buf, PDB_SET);
	for (i = 0; i < LM_HASH_LEN; i++) {
		buf[i] = (uint8) rand();
	}
	pdb_set_lanman_passwd(out, buf, PDB_SET);
	for (i = 0; i < history * PW_HISTORY_ENTRY_LEN; i++) {
		buf[i] = (uint8) rand();
	}
	pdb_set_pw_history(out, buf, history, PDB_SET);

	pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire);
	pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age);
	pdb_set_pass_last_set_time(out, time(NULL), PDB_SET);
	
	if (expire == 0 || expire == (uint32)-1) {
		pdb_set_pass_must_change_time(out, get_time_t_max(), PDB_SET);
	} else {
		pdb_set_pass_must_change_time(out, time(NULL)+expire, PDB_SET);
	}

	if (min_age == (uint32)-1) {
		pdb_set_pass_can_change_time(out, 0, PDB_SET);
	} else {
		pdb_set_pass_can_change_time(out, time(NULL)+min_age, PDB_SET);
	}
	
	/* Create account */
	if (!NT_STATUS_IS_OK(rv = pdb->add_sam_account(pdb, out))) {
		fprintf(stderr, "Error in add_sam_account: %s\n", 
				get_friendly_nt_error_msg(rv));
		exit(1);
	}

	if (!(in = samu_new(ctx))) {
		fprintf(stderr, "Can't create samu structure.\n");
		exit(1);
	}
	
	/* Get account information through getsampwnam() */
	if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, out->username))) {
		fprintf(stderr, "Error getting sampw of added user %s.\n",
				out->username);
		if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
			fprintf(stderr, "Error in delete_sam_account %s\n", 
					get_friendly_nt_error_msg(rv));
		}
		TALLOC_FREE(ctx);
	}
	
	/* Verify integrity */
	if (samu_correct(out, in)) {
		printf("User info written correctly\n");
	} else {
		printf("User info NOT written correctly\n");
		error = True;
	}
	
	/* Delete account */
	if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
		fprintf(stderr, "Error in delete_sam_account %s\n", 
					get_friendly_nt_error_msg(rv));
	}

	pdb->setsampwent(pdb, False, 0);
	while (NT_STATUS_IS_OK(pdb->getsampwent(pdb, out))) {
		if (pdb_get_username(out) == NULL) {
			fprintf(stderr, "Got bad username through getsampwent()\n");
			error = True;
			break;
		}
		if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, pdb_get_username(out)))) {
			fprintf(stderr, "Error getting samu through getsampwnam() of an account we got through getsampwent!\n");
			error = True;
			continue;
		}
		if (!samu_correct(out, in)) {
			printf("Record gotten through getsampwnam() differs from same record through getsampwent()\n");
		}
	}
	pdb->endsampwent(pdb);
	
	TALLOC_FREE(ctx);

	if (error) {
		return 1;
	}
	return 0;
}
Ejemplo n.º 11
0
static int new_machine (struct pdb_methods *in, const char *machine_in)
{
	struct samu *sam_pwent=NULL;
	fstring machinename;
	fstring machineaccount;
	struct passwd  *pwd = NULL;
	
	get_global_sam_sid();

	if (strlen(machine_in) == 0) {
		fprintf(stderr, "No machine name given\n");
		return -1;
	}

	fstrcpy(machinename, machine_in); 
	machinename[15]= '\0';

	if (machinename[strlen (machinename) -1] == '$')
		machinename[strlen (machinename) -1] = '\0';
	
	strlower_m(machinename);
	
	fstrcpy(machineaccount, machinename);
	fstrcat(machineaccount, "$");

	if ((pwd = getpwnam_alloc(NULL, machineaccount))) {

		if ( (sam_pwent = samu_new( NULL )) == NULL ) {
			fprintf(stderr, "Memory allocation error!\n");
			TALLOC_FREE(pwd);
			return -1;
		}

		if ( !NT_STATUS_IS_OK(samu_set_unix(sam_pwent, pwd )) ) {
			fprintf(stderr, "Could not init sam from pw\n");
			TALLOC_FREE(pwd);
			return -1;
		}

		TALLOC_FREE(pwd);
	} else {
		if ( (sam_pwent = samu_new( NULL )) == NULL ) {
			fprintf(stderr, "Could not init sam from pw\n");
			return -1;
		}
	}

	pdb_set_plaintext_passwd (sam_pwent, machinename);
	pdb_set_username (sam_pwent, machineaccount, PDB_CHANGED);	
	pdb_set_acct_ctrl (sam_pwent, ACB_WSTRUST, PDB_CHANGED);
	
	if (NT_STATUS_IS_OK(in->add_sam_account (in, sam_pwent))) {
		print_user_info (in, machineaccount, True, False);
	} else {
		fprintf (stderr, "Unable to add machine! (does it already exist?)\n");
		TALLOC_FREE(sam_pwent);
		return -1;
	}
	TALLOC_FREE(sam_pwent);
	return 0;
}
Ejemplo n.º 12
0
/*********************************************************
 Add New User
**********************************************************/
static int new_user (struct pdb_methods *in, const char *username,
			const char *fullname, const char *homedir,
			const char *drive, const char *script,
			const char *profile, char *user_sid, BOOL stdin_get)
{
	struct samu *sam_pwent;
	char *password1, *password2;
	int rc_pwd_cmp;
	struct passwd *pwd;

	get_global_sam_sid();

	if ( !(pwd = getpwnam_alloc( NULL, username )) ) {
		DEBUG(0,("Cannot locate Unix account for %s\n", username));
		return -1;
	}

	if ( (sam_pwent = samu_new( NULL )) == NULL ) {
		DEBUG(0, ("Memory allocation failure!\n"));
		return -1;
	}

	if (!NT_STATUS_IS_OK(samu_alloc_rid_unix(sam_pwent, pwd ))) {
		TALLOC_FREE( sam_pwent );
		TALLOC_FREE( pwd );
		DEBUG(0, ("could not create account to add new user %s\n", username));
		return -1;
	}

	password1 = get_pass( "new password:"******"retype new password:"******"Passwords do not match!\n");
		TALLOC_FREE(sam_pwent);
	} else {
		pdb_set_plaintext_passwd(sam_pwent, password1);
	}

	memset(password1, 0, strlen(password1));
	SAFE_FREE(password1);
	memset(password2, 0, strlen(password2));
	SAFE_FREE(password2);

	/* pwds do _not_ match? */
	if (rc_pwd_cmp)
		return -1;

	if (fullname)
		pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED);
	if (homedir)
		pdb_set_homedir (sam_pwent, homedir, PDB_CHANGED);
	if (drive)
		pdb_set_dir_drive (sam_pwent, drive, PDB_CHANGED);
	if (script)
		pdb_set_logon_script(sam_pwent, script, PDB_CHANGED);
	if (profile)
		pdb_set_profile_path (sam_pwent, profile, PDB_CHANGED);
	if (user_sid) {
		DOM_SID u_sid;
		if (!string_to_sid(&u_sid, user_sid)) {
			/* not a complete sid, may be a RID, try building a SID */
			int u_rid;
			
			if (sscanf(user_sid, "%d", &u_rid) != 1) {
				fprintf(stderr, "Error passed string is not a complete user SID or RID!\n");
				TALLOC_FREE(sam_pwent);
				return -1;
			}
			sid_copy(&u_sid, get_global_sam_sid());
			sid_append_rid(&u_sid, u_rid);
		}
		pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED);
	}
	
	pdb_set_acct_ctrl (sam_pwent, ACB_NORMAL, PDB_CHANGED);
	
	if (NT_STATUS_IS_OK(in->add_sam_account (in, sam_pwent))) { 
		print_user_info (in, username, True, False);
	} else {
		fprintf (stderr, "Unable to add user! (does it already exist?)\n");
		TALLOC_FREE(sam_pwent);
		return -1;
	}
	TALLOC_FREE(sam_pwent);
	return 0;
}