示例#1
0
文件: vpn.c 项目: gygy/asuswrt
void start_pptpd(void)
{
	int ret = 0, mss = 0, manual_dns = 0, pptpd_opt = 0;
	FILE *fp;

	int pid = getpid();
	_dprintf("start_pptpd: getpid= %d\n", pid);

	if(getpid() != 1) {
		notify_rc("start_pptpd");
		return;
	}

	if (!nvram_match("pptpd_enable", "1")) {
		return;
	}
	// cprintf("stop vpn modules\n");
	// stop_vpn_modules ();

	// Create directory for use by pptpd daemon and its supporting files
	mkdir("/tmp/pptpd", 0744);
	cprintf("open options file\n");
	// Create options file that will be unique to pptpd to avoid interference 
	// with pppoe and pptp
	fp = fopen("/tmp/pptpd/options.pptpd", "w");
	fprintf(fp, "logfile /var/log/pptpd-pppd.log\n");
	//fprintf(fp, "debug dump logfd 2 nodetach\n");
	if (nvram_match("pptpd_radius", "1"))
		fprintf(fp, "plugin radius.so\nplugin radattr.so\n"
			"radius-config-file /tmp/pptpd/radius/radiusclient.conf\n");

	cprintf("check if wan_wins = zero\n");
	int nowins = 0;

	if (nvram_match("wan_wins", "0.0.0.0")) {
		nvram_set("wan_wins", "");
		nowins = 1;
	}
	if (strlen(nvram_safe_get("wan_wins")) == 0)
		nowins = 1;

	cprintf("write config\n");
	fprintf(fp, "lock\n"
		"name *\n"
		"proxyarp\n"
//		"ipcp-accept-local\n"
//		"ipcp-accept-remote\n"
		"lcp-echo-failure 10\n"
		"lcp-echo-interval 6\n"
		"deflate 0\n" "auth\n" "-chap\n"
		"nomppe-stateful\n");

	pptpd_opt = nvram_get_int("pptpd_chap");
	fprintf(fp, "%smschap\n", (pptpd_opt == 0 || pptpd_opt & 1) ? "+" : "-");
	fprintf(fp, "%smschap-v2\n", (pptpd_opt == 0 || pptpd_opt & 2) ? "+" : "-");

	pptpd_opt = nvram_get_int("pptpd_mppe");
	if (pptpd_opt == 0) 
		pptpd_opt = 1 | 4 | 8;
	if (pptpd_opt & (1 | 2 | 4)) {
		fprintf(fp, "%s", (pptpd_opt & 8) ? "" : "require-mppe\n");
  		fprintf(fp, "%smppe-128\n", (pptpd_opt & 1) ? "require-" : "no");
  		fprintf(fp, "%smppe-56\n", (pptpd_opt & 2) ? "require-" : "no");
  		fprintf(fp, "%smppe-40\n", (pptpd_opt & 4) ? "require-" : "no");
	} else
  		fprintf(fp, "nomppe nomppc\n");

	fprintf(fp, "chapms-strip-domain\n"
		"chap-secrets /tmp/pptpd/chap-secrets\n"
		"ip-up-script /tmp/pptpd/ip-up\n"
		"ip-down-script /tmp/pptpd/ip-down\n"
		"mtu %s\n" "mru %s\n",
		nvram_get("pptpd_mtu") ? nvram_get("pptpd_mtu") : "1450",
		nvram_get("pptpd_mru") ? nvram_get("pptpd_mru") : "1450");
	//WINS Server
	if (!nowins) {
		fprintf(fp, "ms-wins %s\n", nvram_safe_get("wan_wins"));
	}
	if (strlen(nvram_safe_get("pptpd_wins1"))) {
		fprintf(fp, "ms-wins %s\n", nvram_safe_get("pptpd_wins1"));
	}
	if (strlen(nvram_safe_get("pptpd_wins2"))) {
		fprintf(fp, "ms-wins %s\n", nvram_safe_get("pptpd_wins2"));
	}
	//DNS Server
	if (strlen(nvram_safe_get("pptpd_dns1"))) {
		fprintf(fp, "ms-dns %s\n", nvram_safe_get("pptpd_dns1"));
		manual_dns=1;
	}
	if (strlen(nvram_safe_get("pptpd_dns2"))) {
		fprintf(fp, "ms-dns %s\n", nvram_safe_get("pptpd_dns2"));
		manual_dns=1;
	}
	if(!manual_dns && !nvram_match("lan_ipaddr", ""))
                fprintf(fp, "ms-dns %s\n", nvram_safe_get("lan_ipaddr"));

	// force ppp interface starting from 10
	fprintf(fp, "minunit 10\n");

	// Following is all crude and need to be revisited once testing confirms
	// that it does work
	// Should be enough for testing..
	if (nvram_match("pptpd_radius", "1")) {
		if (nvram_get("pptpd_radserver") != NULL
		    && nvram_get("pptpd_radpass") != NULL) {

			fclose(fp);

			mkdir("/tmp/pptpd/radius", 0744);

			fp = fopen("/tmp/pptpd/radius/radiusclient.conf", "w");
			fprintf(fp, "auth_order radius\n"
				"login_tries 4\n"
				"login_timeout 60\n"
				"radius_timeout 10\n"
				"nologin /etc/nologin\n"
				"servers /tmp/pptpd/radius/servers\n"
				"dictionary /etc/dictionary\n"
				"seqfile /var/run/radius.seq\n"
				"mapfile /etc/port-id-map\n"
				"radius_retries 3\n"
				"authserver %s:%s\n",
				nvram_get("pptpd_radserver"),
				nvram_get("pptpd_radport") ?
				nvram_get("pptpd_radport") : "radius");

			if (nvram_get("pptpd_radserver") != NULL
			    && nvram_get("pptpd_acctport") != NULL)
				fprintf(fp, "acctserver %s:%s\n",
					nvram_get("pptpd_radserver"),
					nvram_get("pptpd_acctport") ?
					nvram_get("pptpd_acctport") :
					"radacct");
			fclose(fp);

			fp = fopen("/tmp/pptpd/radius/servers", "w");
			fprintf(fp, "%s\t%s\n", nvram_get("pptpd_radserver"),
				nvram_get("pptpd_radpass"));
			fclose(fp);

		} else
			fclose(fp);
	} else
		fclose(fp);

	// Create pptpd.conf options file for pptpd daemon
	fp = fopen("/tmp/pptpd/pptpd.conf", "w");
	fprintf(fp, "localip %s\n"
		"remoteip %s\n", nvram_safe_get("lan_ipaddr"),
		nvram_safe_get("pptpd_clients"));
	if (nvram_invmatch("pptpd_broadcast", "") &&
	    nvram_invmatch("pptpd_broadcast", "disable")) {
		fprintf(fp, "bcrelay %s,%s\n",
			nvram_safe_get("lan_ifname"), "ppp1[0-9].*");
	}

	append_custom_config("pptpd.conf", fp);
	fclose(fp);

	use_custom_config("pptpd.conf", "/tmp/pptpd/pptpd.conf");
	run_postconf("pptpd.postconf", "/tmp/pptpd/pptpd.conf");

	// Create ip-up and ip-down scripts that are unique to pptpd to avoid
	// interference with pppoe and pptp
	/*
	 * adjust for tunneling overhead (mtu - 40 byte IP - 108 byte tunnel
	 * overhead) 
	 */
	if (nvram_match("mtu_enable", "1"))
		mss = nvram_get_int("wan_mtu") - 40 - 108;
	else
		mss = 1500 - 40 - 108;
	char bcast[32];

	strcpy(bcast, nvram_safe_get("lan_ipaddr"));
	get_broadcast(bcast, nvram_safe_get("lan_netmask"));

	fp = fopen("/tmp/pptpd/ip-up", "w");
	fprintf(fp, "#!/bin/sh\n" "startservice set_routes\n"	// reinitialize 
		"echo $PPPD_PID $1 $5 $6 $PEERNAME >> /tmp/pptp_connected\n" 
		"iptables -I INPUT -i $1 -j ACCEPT\n" "iptables -I FORWARD -i $1 -j ACCEPT\n" 
		"iptables -I FORWARD -i $1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n"
		"iptables -t nat -I PREROUTING -i $1 -p udp -m udp --sport 9 -j DNAT --to-destination %s "	// rule for wake on lan over pptp tunnel
		"%s\n", bcast,
		nvram_get("pptpd_ipup_script") ? nvram_get("pptpd_ipup_script") : "");
	fprintf(fp, "iptables -t mangle -A FORWARD -i $1 -m state --state NEW -j MARK --set-mark 0x01/0x7\n");
	fclose(fp);
	fp = fopen("/tmp/pptpd/ip-down", "w");
	fprintf(fp, "#!/bin/sh\n" "grep -v $1  /tmp/pptp_connected > /tmp/pptp_connected.new\n" 
		"mv /tmp/pptp_connected.new /tmp/pptp_connected\n" 
		"iptables -D FORWARD -i $1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu\n" 
		"iptables -D INPUT -i $1 -j ACCEPT\n" 
		"iptables -D FORWARD -i $1 -j ACCEPT\n" 
		"iptables -t nat -D PREROUTING -i $1 -p udp -m udp --sport 9 -j DNAT --to-destination %s "	// rule for wake on lan over pptp tunnel
		"%s\n", bcast,
		nvram_get("pptpd_ipdown_script") ? nvram_get("pptpd_ipdown_script") : "");
	fprintf(fp, "iptables -t mangle -D FORWARD -i $1 -m state --state NEW -j MARK --set-mark 0x01/0x7\n");
	fclose(fp);
	chmod("/tmp/pptpd/ip-up", 0744);
	chmod("/tmp/pptpd/ip-down", 0744);

	// Exctract chap-secrets from nvram
	write_chap_secret("/tmp/pptpd/chap-secrets");

	chmod("/tmp/pptpd/chap-secrets", 0600);

	// Execute pptpd daemon
	ret =
	    eval("pptpd", "-c", "/tmp/pptpd/pptpd.conf", "-o",
		 "/tmp/pptpd/options.pptpd");

	_dprintf("start_pptpd: ret= %d\n", ret);
	//dd_syslog(LOG_INFO, "pptpd : pptp daemon successfully started\n");
	return;
}
示例#2
0
int main(int argc, char *argv[])
{
	FILE *fp;
	char *nv;
	int n=0;
	char *p_computer_name = NULL;
	disk_info_t *follow_disk, *disks_info = NULL;
	partition_info_t *follow_partition;
	char *mount_folder;
	int result, node_layer, samba_right;
	int sh_num;
	char **folder_list = NULL;
	int acc_num;
	char **account_list;
	int dup, same_m_pt = 0;
	char unique_share_name[PATH_MAX];

	unlink("/var/log.samba");

	if ((fp=fopen(SAMBA_CONF, "r"))) {
		fclose(fp);
		unlink(SAMBA_CONF);
	}

	if((fp = fopen(SAMBA_CONF, "w")) == NULL)
		goto confpage;

	fprintf(fp, "[global]\n");
	if (nvram_safe_get("st_samba_workgroup"))
		fprintf(fp, "workgroup = %s\n", nvram_safe_get("st_samba_workgroup"));
#if 0
	if (nvram_safe_get("computer_name")) {
		fprintf(fp, "netbios name = %s\n", nvram_safe_get("computer_name"));
		fprintf(fp, "server string = %s\n", nvram_safe_get("computer_name"));
	}
#else
	p_computer_name = nvram_get("computer_name") && is_valid_netbios_name(nvram_get("computer_name")) ? nvram_get("computer_name") : get_productid();
	if (p_computer_name) {
		fprintf(fp, "netbios name = %s\n", p_computer_name);
		fprintf(fp, "server string = %s\n", p_computer_name);
	}
#endif

	fprintf(fp, "unix charset = UTF8\n");		// ASUS add
	fprintf(fp, "display charset = UTF8\n");	// ASUS add
	fprintf(fp, "log file = /var/log.samba\n");
	fprintf(fp, "log level = 0\n");
	fprintf(fp, "max log size = 5\n");

	// account mode
	if(nvram_match("st_samba_mode", "2") || nvram_match("st_samba_mode", "4")
			|| (nvram_match("st_samba_mode", "1") && nvram_get("st_samba_force_mode") == NULL)
			){
		fprintf(fp, "security = USER\n");
		fprintf(fp, "guest ok = no\n");
		fprintf(fp, "map to guest = Bad User\n");
	}
	// share mode
	else if (nvram_match("st_samba_mode", "1") || nvram_match("st_samba_mode", "3")) {
#if 0
//#if defined(RTCONFIG_TFAT) || defined(RTCONFIG_TUXERA_NTFS) || defined(RTCONFIG_TUXERA_HFS)
		if(nvram_get_int("enable_samba_tuxera") == 1){
			fprintf(fp, "auth methods = guest\n");
			fprintf(fp, "guest account = admin\n");
			fprintf(fp, "map to guest = Bad Password\n");
			fprintf(fp, "guest ok = yes\n");
		}
		else{
			fprintf(fp, "security = SHARE\n");
			fprintf(fp, "guest only = yes\n");
		}
#else
		fprintf(fp, "security = SHARE\n");
		fprintf(fp, "guest only = yes\n");
#endif
	}
	else{
		usb_dbg("samba mode: no\n");
		goto confpage;
	}

	fprintf(fp, "encrypt passwords = yes\n");
	fprintf(fp, "pam password change = no\n");
	fprintf(fp, "null passwords = yes\n");		// ASUS add
#ifdef RTCONFIG_SAMBA_MODERN
	if (nvram_get_int("smbd_enable_smb2"))
		fprintf(fp, "max protocol = SMB2\n");
	else
		fprintf(fp, "max protocol = NT1\n");

	fprintf(fp, "passdb backend = smbpasswd\n");
	fprintf(fp, "smb encrypt = disabled\n");
	fprintf(fp, "smb passwd file = /etc/samba/smbpasswd\n");
#endif
#if 0
#ifdef RTCONFIG_RECVFILE
	fprintf(fp, "use recvfile = yes\n");
#endif
#endif
	fprintf(fp, "force directory mode = 0777\n");
	fprintf(fp, "force create mode = 0777\n");

	/* max users */
	if (strcmp(nvram_safe_get("st_max_user"), "") != 0)
		fprintf(fp, "max connections = %s\n", nvram_safe_get("st_max_user"));

        /* remove socket options due to NIC compatible issue */
	if(!nvram_get_int("stop_samba_speedup")){
#ifdef RTCONFIG_BCMARM
#ifdef RTCONFIG_BCM_7114
		fprintf(fp, "socket options = IPTOS_LOWDELAY TCP_NODELAY SO_RCVBUF=131072 SO_SNDBUF=131072\n");
#endif
#else
		fprintf(fp, "socket options = TCP_NODELAY SO_KEEPALIVE SO_RCVBUF=65536 SO_SNDBUF=65536\n");
#endif
	}
	fprintf(fp, "obey pam restrictions = no\n");
	fprintf(fp, "use spnego = no\n");		// ASUS add
	fprintf(fp, "client use spnego = no\n");	// ASUS add
//	fprintf(fp, "client use spnego = yes\n");  // ASUS add
	fprintf(fp, "disable spoolss = yes\n");		// ASUS add
	fprintf(fp, "host msdfs = no\n");		// ASUS add
	fprintf(fp, "strict allocate = No\n");		// ASUS add
//	fprintf(fp, "mangling method = hash2\n");	// ASUS add
	fprintf(fp, "bind interfaces only = yes\n");    // ASUS add

#ifndef RTCONFIG_BCMARM
	fprintf(fp, "interfaces = lo br0 %s\n", (is_routing_enabled() && nvram_get_int("smbd_wanac")) ? nvram_safe_get("wan0_ifname") : "");
#else
	fprintf(fp, "interfaces = br0 %s/%s %s\n", nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask"), (is_routing_enabled() && nvram_get_int("smbd_wanac")) ? nvram_safe_get("wan0_ifname") : "");
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
	fprintf(fp, "use sendfile = no\n");
#else
	fprintf(fp, "use sendfile = yes\n");
#endif
	if (!strcmp(nvram_safe_get("smbd_wins"), "1")) {
		fprintf(fp, "wins support = yes\n");
	}

	if (!strcmp(nvram_safe_get("smbd_master"), "1")) {
		fprintf(fp, "os level = 255\n");
		fprintf(fp, "domain master = yes\n");
		fprintf(fp, "local master = yes\n");
		fprintf(fp, "preferred master = yes\n");
	}

	fprintf(fp, "map archive = no\n");
	fprintf(fp, "map hidden = no\n");
	fprintf(fp, "map read only = no\n");
	fprintf(fp, "map system = no\n");
	fprintf(fp, "store dos attributes = yes\n");
	fprintf(fp, "dos filemode = yes\n");
	fprintf(fp, "oplocks = yes\n");
	fprintf(fp, "level2 oplocks = yes\n");
	fprintf(fp, "kernel oplocks = no\n");
	fprintf(fp, "wide links = no\n");

	// If we only want name services then skip share definition
	if (nvram_match("enable_samba", "0"))
		goto confpage;

	disks_info = read_disk_data();
	if (disks_info == NULL) {
		usb_dbg("Couldn't get disk list when writing smb.conf!\n");
		goto confpage;
	}

	/* share */
	if (nvram_match("st_samba_mode", "0") || !strcmp(nvram_safe_get("st_samba_mode"), "")) {
		;
	}
	else if (nvram_match("st_samba_mode", "1") && nvram_match("st_samba_force_mode", "1")) {
		usb_dbg("samba mode: share\n");

		for (follow_disk = disks_info; follow_disk != NULL; follow_disk = follow_disk->next) {
			for (follow_partition = follow_disk->partitions; follow_partition != NULL; follow_partition = follow_partition->next) {
				if (follow_partition->mount_point == NULL)
					continue;
				
				strcpy(unique_share_name, follow_partition->mount_point);
				do {
					dup = check_mount_point_icase(disks_info, follow_partition, follow_disk, follow_partition->partition_order, unique_share_name);
					if (dup)
						sprintf(unique_share_name, "%s(%d)", follow_partition->mount_point, ++same_m_pt);
				} while (dup);
				mount_folder = strrchr(unique_share_name, '/')+1;

				fprintf(fp, "[%s]\n", mount_folder);
				fprintf(fp, "comment = %s's %s\n", follow_disk->tag, mount_folder);
				fprintf(fp, "veto files = /.__*.txt*/asus_lighttpdpasswd/\n");
				fprintf(fp, "path = %s\n", follow_partition->mount_point);
				fprintf(fp, "writeable = yes\n");

				fprintf(fp, "dos filetimes = yes\n");
				fprintf(fp, "fake directory create times = yes\n");
			}
		}
	}
	else if (nvram_match("st_samba_mode", "2")) {
		usb_dbg("samba mode: share\n");

		for (follow_disk = disks_info; follow_disk != NULL; follow_disk = follow_disk->next) {
			for (follow_partition = follow_disk->partitions; follow_partition != NULL; follow_partition = follow_partition->next) {
				if (follow_partition->mount_point == NULL)
					continue;

				strcpy(unique_share_name, follow_partition->mount_point);
				do {
					dup = check_mount_point_icase(disks_info, follow_partition, follow_disk, follow_partition->partition_order, unique_share_name);
					if (dup)
						sprintf(unique_share_name, "%s(%d)", follow_partition->mount_point, ++same_m_pt);
				} while (dup);
				mount_folder = strrchr(unique_share_name, '/')+1;

				node_layer = get_permission(NULL, follow_partition->mount_point, NULL, "cifs");
				if(node_layer == 3){
					fprintf(fp, "[%s]\n", mount_folder);
					fprintf(fp, "comment = %s's %s\n", follow_disk->tag, mount_folder);
					fprintf(fp, "path = %s\n", follow_partition->mount_point);
					fprintf(fp, "writeable = yes\n");

					fprintf(fp, "dos filetimes = yes\n");
					fprintf(fp, "fake directory create times = yes\n");
				}
				else{
					//result = get_all_folder(follow_partition->mount_point, &sh_num, &folder_list);
					result = get_folder_list(follow_partition->mount_point, &sh_num, &folder_list);
					if (result < 0){
						free_2_dimension_list(&sh_num, &folder_list);
						continue;
					}

					for (n = 0; n < sh_num; ++n){
						samba_right = get_permission(NULL, follow_partition->mount_point, folder_list[n], "cifs");
						if (samba_right < 0 || samba_right > 3)
							samba_right = DEFAULT_SAMBA_RIGHT;

						if(samba_right > 0){
							int count = get_list_strings_count(folder_list, sh_num, folder_list[n]);
							if ((!strcmp(nvram_safe_get("smbd_simpler_naming"), "1")) && (count <= 1)) {
								fprintf(fp, "[%s]\n", folder_list[n]);
							} else {
								fprintf(fp, "[%s (at %s)]\n", folder_list[n], mount_folder);
							}
							fprintf(fp, "comment = %s's %s in %s\n", mount_folder, folder_list[n], follow_disk->tag);
							fprintf(fp, "path = %s/%s\n", follow_partition->mount_point, folder_list[n]);
							if(samba_right == 3)
								fprintf(fp, "writeable = yes\n");
							else
								fprintf(fp, "writeable = no\n");

							fprintf(fp, "dos filetimes = yes\n");
							fprintf(fp, "fake directory create times = yes\n");
						}
					}

					free_2_dimension_list(&sh_num, &folder_list);
				}
			}
		}
	}
	else if (nvram_match("st_samba_mode", "3")) {
		usb_dbg("samba mode: user\n");

		// get the account list
		if (get_account_list(&acc_num, &account_list) < 0) {
			usb_dbg("Can't read the account list.\n");
			free_2_dimension_list(&acc_num, &account_list);
			goto confpage;
		}

		for (follow_disk = disks_info; follow_disk != NULL; follow_disk = follow_disk->next) {
			for (follow_partition = follow_disk->partitions; follow_partition != NULL; follow_partition = follow_partition->next) {
				if (follow_partition->mount_point == NULL)
					continue;

				mount_folder = strrchr(follow_partition->mount_point, '/')+1;

				// 1. get the folder list
				if (get_folder_list(follow_partition->mount_point, &sh_num, &folder_list) < 0) {
					free_2_dimension_list(&sh_num, &folder_list);
				}

				// 2. start to get every share
				for (n = -1; n < sh_num; ++n) {
					int i, first;

					if(n == -1){
						fprintf(fp, "[%s]\n", mount_folder);
						fprintf(fp, "comment = %s's %s\n", follow_disk->tag, mount_folder);
						fprintf(fp, "path = %s\n", follow_partition->mount_point);
					}
					else{
						int count = get_list_strings_count(folder_list, sh_num, folder_list[n]);
						if ((!strcmp(nvram_safe_get("smbd_simpler_naming"), "1")) && (count <= 1)) {
							fprintf(fp, "[%s]\n", folder_list[n]);
						} else {
							fprintf(fp, "[%s (at %s)]\n", folder_list[n], mount_folder);
						}
						fprintf(fp, "comment = %s's %s in %s\n", mount_folder, folder_list[n], follow_disk->tag);
						fprintf(fp, "path = %s/%s\n", follow_partition->mount_point, folder_list[n]);
					}

					fprintf(fp, "dos filetimes = yes\n");
					fprintf(fp, "fake directory create times = yes\n");

					fprintf(fp, "valid users = ");
					first = 1;
					for (i = 0; i < acc_num; ++i) {
						if(n == -1)
							samba_right = get_permission(account_list[i], follow_partition->mount_point, NULL, "cifs");
						else
							samba_right = get_permission(account_list[i], follow_partition->mount_point, folder_list[n], "cifs");
						if (first == 1)
							first = 0;
						else
							fprintf(fp, ", ");

						fprintf(fp, "%s", account_list[i]);
					}
					fprintf(fp, "\n");

					fprintf(fp, "invalid users = ");
					first = 1;
					for (i = 0; i < acc_num; ++i) {
						if(n == -1)
							samba_right = get_permission(account_list[i], follow_partition->mount_point, NULL, "cifs");
						else
							samba_right = get_permission(account_list[i], follow_partition->mount_point, folder_list[n], "cifs");
						if (samba_right >= 1)
							continue;
						
						if (first == 1)
							first = 0;
						else
							fprintf(fp, ", ");

						fprintf(fp, "%s", account_list[i]);
					}
					fprintf(fp, "\n");

					fprintf(fp, "read list = ");
					first = 1;
					for (i = 0; i < acc_num; ++i) {
						if(n == -1)
							samba_right = get_permission(account_list[i], follow_partition->mount_point, NULL, "cifs");
						else
							samba_right = get_permission(account_list[i], follow_partition->mount_point, folder_list[n], "cifs");
						if (samba_right < 1)
							continue;

						if (first == 1)
							first = 0;
						else
							fprintf(fp, ", ");

						fprintf(fp, "%s", account_list[i]);
					}
					fprintf(fp, "\n");

					fprintf(fp, "write list = ");
					first = 1;
					for (i = 0; i < acc_num; ++i) {
						if(n == -1)
							samba_right = get_permission(account_list[i], follow_partition->mount_point, NULL, "cifs");
						else
							samba_right = get_permission(account_list[i], follow_partition->mount_point, folder_list[n], "cifs");
						if (samba_right < 2)
							continue;

						if (first == 1)
							first = 0;
						else
							fprintf(fp, ", ");

						fprintf(fp, "%s", account_list[i]);
					}
					fprintf(fp, "\n");
				}

				free_2_dimension_list(&sh_num, &folder_list);
			}
		}

		free_2_dimension_list(&acc_num, &account_list);
	}
	else if (nvram_match("st_samba_mode", "4")
			|| (nvram_match("st_samba_mode", "1") && nvram_get("st_samba_force_mode") == NULL)
			) {
		usb_dbg("samba mode: user\n");

		// get the account list
		if (get_account_list(&acc_num, &account_list) < 0) {
			usb_dbg("Can't read the account list.\n");
			free_2_dimension_list(&acc_num, &account_list);
			goto confpage;
		}

		for (follow_disk = disks_info; follow_disk != NULL; follow_disk = follow_disk->next) {
			for (follow_partition = follow_disk->partitions; follow_partition != NULL; follow_partition = follow_partition->next) {
				if (follow_partition->mount_point == NULL)
					continue;

				mount_folder = strrchr(follow_partition->mount_point, '/')+1;

				// 1. get the folder list
				if (get_folder_list(follow_partition->mount_point, &sh_num, &folder_list) < 0) {
					free_2_dimension_list(&sh_num, &folder_list);
				}

				// 2. start to get every share
				for (n = 0; n < sh_num; ++n) {
					int i, first;

					int count = get_list_strings_count(folder_list, sh_num, folder_list[n]);
					if ((!strcmp(nvram_safe_get("smbd_simpler_naming"), "1")) && (count <= 1)) {
						fprintf(fp, "[%s]\n", folder_list[n]);
					} else {
						fprintf(fp, "[%s (at %s)]\n", folder_list[n], mount_folder);
					}
					fprintf(fp, "comment = %s's %s in %s\n", mount_folder, folder_list[n], follow_disk->tag);
					fprintf(fp, "path = %s/%s\n", follow_partition->mount_point, folder_list[n]);

					fprintf(fp, "dos filetimes = yes\n");
					fprintf(fp, "fake directory create times = yes\n");

					fprintf(fp, "valid users = ");
					first = 1;
					for (i = 0; i < acc_num; ++i) {
						if(n == -1)
							samba_right = get_permission(account_list[i], follow_partition->mount_point, NULL, "cifs");
						else
							samba_right = get_permission(account_list[i], follow_partition->mount_point, folder_list[n], "cifs");
						if (first == 1)
							first = 0;
						else
							fprintf(fp, ", ");

						fprintf(fp, "%s", account_list[i]);
					}
					fprintf(fp, "\n");

					fprintf(fp, "invalid users = ");
					first = 1;
					for (i = 0; i < acc_num; ++i) {
						samba_right = get_permission(account_list[i], follow_partition->mount_point, folder_list[n], "cifs");
						if (samba_right >= 1)
							continue;
						
						if (first == 1)
							first = 0;
						else
							fprintf(fp, ", ");

						fprintf(fp, "%s", account_list[i]);
					}
					fprintf(fp, "\n");

					fprintf(fp, "read list = ");
					first = 1;
					for (i = 0; i < acc_num; ++i) {
						samba_right = get_permission(account_list[i], follow_partition->mount_point, folder_list[n], "cifs");
						if (samba_right < 1)
							continue;

						if (first == 1)
							first = 0;
						else
							fprintf(fp, ", ");

						fprintf(fp, "%s", account_list[i]);
					}
					fprintf(fp, "\n");

					fprintf(fp, "write list = ");
					first = 1;
					for (i = 0; i < acc_num; ++i) {
						samba_right = get_permission(account_list[i], follow_partition->mount_point, folder_list[n], "cifs");
						if (samba_right < 2)
							continue;

						if (first == 1)
							first = 0;
						else
							fprintf(fp, ", ");

						fprintf(fp, "%s", account_list[i]);
					}
					fprintf(fp, "\n");
				}

				free_2_dimension_list(&sh_num, &folder_list);
			}
		}

		free_2_dimension_list(&acc_num, &account_list);
	}

confpage:
	if(fp != NULL) {

		append_custom_config("smb.conf", fp);
		fclose(fp);

		use_custom_config("smb.conf", SAMBA_CONF);
		run_postconf("smb", SAMBA_CONF);
	}

	free_disk_data(&disks_info);
	return 0;
}