Пример #1
0
static int atalk_unlink(struct vfs_handle_struct *handle,
			const struct smb_filename *smb_fname)
{
	int ret = 0, i;
	char *path = NULL;
	char *adbl_path = NULL;
	char *orig_path = NULL;
	SMB_STRUCT_STAT adbl_info;
	SMB_STRUCT_STAT orig_info;
	NTSTATUS status;

	ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);

	status = get_full_smb_filename(talloc_tos(), smb_fname, &path);
	if (!NT_STATUS_IS_OK(status)) {
		return ret;
	}

	/* no .AppleDouble sync if veto or hide list is empty,
	 * otherwise "Cannot find the specified file" error will be caused
	 */

	if (!handle->conn->veto_list) return ret;
	if (!handle->conn->hide_list) return ret;

	for (i = 0; handle->conn->veto_list[i].name; i ++) {
		if (strstr_m(handle->conn->veto_list[i].name, APPLEDOUBLE))
			break;
	}

	if (!handle->conn->veto_list[i].name) {
		for (i = 0; handle->conn->hide_list[i].name; i ++) {
			if (strstr_m(handle->conn->hide_list[i].name, APPLEDOUBLE))
				break;
			else {
				DEBUG(3, ("ATALK: %s is not hidden, skipped..\n",
				  APPLEDOUBLE));		
				goto exit_unlink;
			}
		}
	}

	if (atalk_build_paths(talloc_tos(), handle->conn->cwd, path,
			      &adbl_path, &orig_path,
			      &adbl_info, &orig_info) != 0)
		goto exit_unlink;

	if (S_ISDIR(orig_info.st_ex_mode) || S_ISREG(orig_info.st_ex_mode)) {
		DEBUG(3, ("ATALK: %s has passed..\n", adbl_path));
		goto exit_unlink;
	}

	atalk_unlink_file(adbl_path);

exit_unlink:
	TALLOC_FREE(path);
	TALLOC_FREE(adbl_path);
	TALLOC_FREE(orig_path);
	return ret;
}
Пример #2
0
static int atalk_build_paths(TALLOC_CTX *ctx, const char *path,
			     const char *fname,
			     char **adbl_path, char **orig_path,
			     SMB_STRUCT_STAT *adbl_info,
			     SMB_STRUCT_STAT *orig_info)
{
	int ptr0 = 0;
	int ptr1 = 0;
	char *dname = 0;
	char *name  = 0;

	if (!ctx || !path || !fname || !adbl_path || !orig_path ||
		!adbl_info || !orig_info)
		return -1;
#if 0
	DEBUG(3, ("ATALK: PATH: %s[%s]\n", path, fname));
#endif
	if (strstr_m(path, APPLEDOUBLE) || strstr_m(fname, APPLEDOUBLE)) {
		DEBUG(3, ("ATALK: path %s[%s] already contains %s\n", path, fname, APPLEDOUBLE));
		return -1;
	}

	if (fname[0] == '.') ptr0 ++;
	if (fname[1] == '/') ptr0 ++;

	*orig_path = talloc_asprintf(ctx, "%s/%s", path, &fname[ptr0]);

	/* get pointer to last '/' */
	ptr1 = atalk_get_path_ptr(*orig_path);

	sys_lstat(*orig_path, orig_info, false);

	if (S_ISDIR(orig_info->st_ex_mode)) {
		*adbl_path = talloc_asprintf(ctx, "%s/%s/%s/", 
		  path, &fname[ptr0], APPLEDOUBLE);
	} else {
		dname = talloc_strdup(ctx, *orig_path);
		dname[ptr1] = '\0';
		name = *orig_path;
		*adbl_path = talloc_asprintf(ctx, "%s/%s/%s", 
		  dname, APPLEDOUBLE, &name[ptr1 + 1]);
	}
#if 0
	DEBUG(3, ("ATALK: DEBUG:\n%s\n%s\n", *orig_path, *adbl_path)); 
#endif
	sys_lstat(*adbl_path, adbl_info, false);
	return 0;
}
Пример #3
0
static int atalk_rmdir(struct vfs_handle_struct *handle,
			const struct smb_filename *smb_fname)
{
	bool add = False;
	TALLOC_CTX *ctx = 0;
	const char *path = smb_fname->base_name;
	char *dpath;

	if (!handle->conn->cwd || !path) goto exit_rmdir;

	/* due to there is no way to change bDeleteVetoFiles variable
	 * from this module, gotta use talloc stuff..
	 */

	strstr_m(path, APPLEDOUBLE) ? (add = False) : (add = True);

	if (!(ctx = talloc_init("remove_directory")))
		goto exit_rmdir;

	if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", 
	  handle->conn->cwd, path, add ? "/"APPLEDOUBLE : "")))
		goto exit_rmdir;

	atalk_rrmdir(ctx, dpath);

exit_rmdir:
	talloc_destroy(ctx);
	return SMB_VFS_NEXT_RMDIR(handle, smb_fname);
}
Пример #4
0
static void atalk_add_to_list(name_compare_entry **list)
{
	int i, count = 0;
	name_compare_entry *new_list = 0;
	name_compare_entry *cur_list = 0;

	cur_list = *list;

	if (cur_list) {
		for (i = 0, count = 0; cur_list[i].name; i ++, count ++) {
			if (strstr_m(cur_list[i].name, APPLEDOUBLE))
				return;
		}
	}

	if (!(new_list = SMB_CALLOC_ARRAY(name_compare_entry, count + 2)))
		return;

	for (i = 0; i < count; i ++) {
		new_list[i].name    = SMB_STRDUP(cur_list[i].name);
		new_list[i].is_wild = cur_list[i].is_wild;
	}

	new_list[i].name    = SMB_STRDUP(APPLEDOUBLE);
	new_list[i].is_wild = False;

	free_namearray(*list);

	*list = new_list;
	new_list = 0;
	cur_list = 0;
}
Пример #5
0
static PyObject *py_strstr_m(PyObject *self, PyObject *args)
{
	char *s1, *s2, *ret;

	if (!PyArg_ParseTuple(args, "ss", &s1, &s2))
		return NULL;

	ret = strstr_m(s1, s2);
	if (!ret) {
		Py_RETURN_NONE;
	}
	return PyString_FromString(ret);
}
Пример #6
0
static NTSTATUS fss_unc_parse(TALLOC_CTX *mem_ctx,
			      const char *unc,
			      char **_server,
			      char **_share)
{
	char *s;
	char *server;
	char *share;

	if (unc == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	s = strstr_m(unc, "\\\\");
	if (s == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	server = talloc_strdup(mem_ctx, s + 2);
	if (server == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	s = strchr_m(server, '\\');
	if ((s == NULL) || (s == server)) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	*s = '\0';
	share = s + 1;

	s = strchr_m(share, '\\');
	if (s != NULL) {
		/* diskshadow.exe adds a trailing '\' to the share-name */
		*s = '\0';
	}
	if (strlen(share) == 0) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (_server != NULL) {
		*_server = server;
	}
	if (_share != NULL) {
		*_share = share;
	}

	return NT_STATUS_OK;
}
Пример #7
0
/*
  make very sure it is one of our special names 
 */
static inline bool shadow_copy2_match_name(const char *name, const char **gmt_start)
{
	unsigned year, month, day, hr, min, sec;
	const char *p;
	if (gmt_start) {
		(*gmt_start) = NULL;
	}
	p = strstr_m(name, "@GMT-");
	if (p == NULL) return false;
	if (p > name && p[-1] != '/') return False;
	if (sscanf(p, "@GMT-%04u.%02u.%02u-%02u.%02u.%02u", &year, &month,
		   &day, &hr, &min, &sec) != 6) {
		return False;
	}
	if (p[24] != 0 && p[24] != '/') {
		return False;
	}
	if (gmt_start) {
		(*gmt_start) = p;
	}
	return True;
}
Пример #8
0
int find_service(fstring service)
{
	int iService;
	struct smbd_server_connection *sconn = smbd_server_conn;

	all_string_sub(service,"\\","/",0);

	iService = lp_servicenumber(service);

	/* now handle the special case of a home directory */
	if (iService < 0) {
		char *phome_dir = get_user_home_dir(talloc_tos(), service);

		if(!phome_dir) {
			/*
			 * Try mapping the servicename, it may
			 * be a Windows to unix mapped user name.
			 */
			if(map_username(sconn, service))
				phome_dir = get_user_home_dir(
					talloc_tos(), service);
		}

		DEBUG(3,("checking for home directory %s gave %s\n",service,
			phome_dir?phome_dir:"(NULL)"));

		iService = add_home_service(service,service /* 'username' */, phome_dir);
	}

	/* If we still don't have a service, attempt to add it as a printer. */
	if (iService < 0) {
		int iPrinterService;

		if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
			iPrinterService = load_registry_service(PRINTERS_NAME);
		}
		if (iPrinterService) {
			DEBUG(3,("checking whether %s is a valid printer name...\n", service));
			if (pcap_printername_ok(service)) {
				DEBUG(3,("%s is a valid printer name\n", service));
				DEBUG(3,("adding %s as a printer service\n", service));
				lp_add_printer(service, iPrinterService);
				iService = lp_servicenumber(service);
				if (iService < 0) {
					DEBUG(0,("failed to add %s as a printer service!\n", service));
				}
			} else {
				DEBUG(3,("%s is not a valid printer name\n", service));
			}
		}
	}

	/* Check for default vfs service?  Unsure whether to implement this */
	if (iService < 0) {
	}

	if (iService < 0) {
		iService = load_registry_service(service);
	}

	/* Is it a usershare service ? */
	if (iService < 0 && *lp_usershare_path()) {
		/* Ensure the name is canonicalized. */
		strlower_m(service);
		iService = load_usershare_service(service);
	}

	/* just possibly it's a default service? */
	if (iService < 0) {
		char *pdefservice = lp_defaultservice();
		if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
			/*
			 * We need to do a local copy here as lp_defaultservice() 
			 * returns one of the rotating lp_string buffers that
			 * could get overwritten by the recursive find_service() call
			 * below. Fix from Josef Hinteregger <*****@*****.**>.
			 */
			char *defservice = SMB_STRDUP(pdefservice);

			if (!defservice) {
				goto fail;
			}

			/* Disallow anything except explicit share names. */
			if (strequal(defservice,HOMES_NAME) ||
					strequal(defservice, PRINTERS_NAME) ||
					strequal(defservice, "IPC$")) {
				SAFE_FREE(defservice);
				goto fail;
			}

			iService = find_service(defservice);
			if (iService >= 0) {
				all_string_sub(service, "_","/",0);
				iService = lp_add_service(service, iService);
			}
			SAFE_FREE(defservice);
		}
	}

	if (iService >= 0) {
		if (!VALID_SNUM(iService)) {
			DEBUG(0,("Invalid snum %d for %s\n",iService, service));
			iService = -1;
		}
	}

  fail:

	if (iService < 0)
		DEBUG(3,("find_service() failed to find service %s\n", service));

	return (iService);
}
Пример #9
0
bool aix_cache_reload(void)
{
	int iEtat;
	XFILE *pfile;
	char *line = NULL, *p;
	char *name = NULL;
	TALLOC_CTX *ctx = talloc_init("aix_cache_reload");

	if (!ctx) {
		return false;
	}

	DEBUG(5, ("reloading aix printcap cache\n"));

	if ((pfile = x_fopen(lp_printcapname(), O_RDONLY, 0)) == NULL) {
		DEBUG(0,( "Unable to open qconfig file %s for read!\n", lp_printcapname()));
		TALLOC_FREE(ctx);
		return false;
	}

	iEtat = 0;
	/* scan qconfig file for searching <printername>:	*/
	for (;(line = fgets_slash(NULL, 1024, pfile)); free(line)) {
		if (*line == '*' || *line == 0)
			continue;

		switch (iEtat) {
		case 0: /* locate an entry */
			if (*line == '\t' || *line == ' ')
				continue;

			if ((p = strchr_m(line, ':'))) {
				char *saveptr;
				*p = '\0';
				p = strtok_r(line, ":", &saveptr);
				if (strcmp(p, "bsh") != 0) {
					name = talloc_strdup(ctx, p);
					if (!name) {
						SAFE_FREE(line);
						x_fclose(pfile);
						TALLOC_FREE(ctx);
						return false;
					}
					iEtat = 1;
					continue;
				}
			 }
			 break;

		case 1: /* scanning device stanza */
			if (*line == '*' || *line == 0)
				continue;

			if (*line != '\t' && *line != ' ') {
				/* name is found without stanza device  */
				/* probably a good printer ???		*/
				iEtat = 0;
				if (!pcap_cache_add(name, NULL)) {
					SAFE_FREE(line);
					x_fclose(pfile);
					TALLOC_FREE(ctx);
					return false;
				}
				continue;
			}

			if (strstr_m(line, "backend")) {
				/* it's a device, not a virtual printer */
				iEtat = 0;
			} else if (strstr_m(line, "device")) {
				/* it's a good virtual printer */
				iEtat = 0;
				if (!pcap_cache_add(name, NULL)) {
					SAFE_FREE(line);
					x_fclose(pfile);
					TALLOC_FREE(ctx);
					return false;
				}
				continue;
			}
			break;
		}
	}

	x_fclose(pfile);
	TALLOC_FREE(ctx);
	return true;
}
Пример #10
0
static void manage_ntlm_server_1_request(enum stdio_helper_mode stdio_helper_mode, 
					 char *buf, int length) 
{
	char *request, *parameter;	
	static DATA_BLOB challenge;
	static DATA_BLOB lm_response;
	static DATA_BLOB nt_response;
	static char *full_username;
	static char *username;
	static char *domain;
	static char *plaintext_password;
	static BOOL ntlm_server_1_user_session_key;
	static BOOL ntlm_server_1_lm_session_key;
	
	if (strequal(buf, ".")) {
		if (!full_username && !username) {	
			x_fprintf(x_stdout, "Error: No username supplied!\n");
		} else if (plaintext_password) {
			/* handle this request as plaintext */
			if (!full_username) {
				if (asprintf(&full_username, "%s%c%s", domain, winbind_separator(), username) == -1) {
					x_fprintf(x_stdout, "Error: Out of memory in asprintf!\n.\n");
					return;
				}
			}
			if (check_plaintext_auth(full_username, plaintext_password, False)) {
				x_fprintf(x_stdout, "Authenticated: Yes\n");
			} else {
				x_fprintf(x_stdout, "Authenticated: No\n");
			}
		} else if (!lm_response.data && !nt_response.data) {
			x_fprintf(x_stdout, "Error: No password supplied!\n");
		} else if (!challenge.data) {	
			x_fprintf(x_stdout, "Error: No lanman-challenge supplied!\n");
		} else {
			char *error_string = NULL;
			uchar lm_key[8];
			uchar user_session_key[16];
			uint32 flags = 0;

			if (full_username && !username) {
				fstring fstr_user;
				fstring fstr_domain;
				
				if (!parse_ntlm_auth_domain_user(full_username, fstr_user, fstr_domain)) {
					/* username might be 'tainted', don't print into our new-line deleimianted stream */
					x_fprintf(x_stdout, "Error: Could not parse into domain and username\n");
				}
				SAFE_FREE(username);
				SAFE_FREE(domain);
				username = smb_xstrdup(fstr_user);
				domain = smb_xstrdup(fstr_domain);
			}

			if (!domain) {
				domain = smb_xstrdup(get_winbind_domain());
			}

			if (ntlm_server_1_lm_session_key) 
				flags |= WBFLAG_PAM_LMKEY;
			
			if (ntlm_server_1_user_session_key) 
				flags |= WBFLAG_PAM_USER_SESSION_KEY;

			if (!NT_STATUS_IS_OK(
				    contact_winbind_auth_crap(username, 
							      domain, 
							      global_myname(),
							      &challenge, 
							      &lm_response, 
							      &nt_response, 
							      flags, 
							      lm_key, 
							      user_session_key,
							      &error_string,
							      NULL))) {

				x_fprintf(x_stdout, "Authenticated: No\n");
				x_fprintf(x_stdout, "Authentication-Error: %s\n.\n", error_string);
				SAFE_FREE(error_string);
			} else {
				static char zeros[16];
				char *hex_lm_key;
				char *hex_user_session_key;

				x_fprintf(x_stdout, "Authenticated: Yes\n");

				if (ntlm_server_1_lm_session_key 
				    && (memcmp(zeros, lm_key, 
					       sizeof(lm_key)) != 0)) {
					hex_lm_key = hex_encode(NULL,
								(const unsigned char *)lm_key,
								sizeof(lm_key));
					x_fprintf(x_stdout, "LANMAN-Session-Key: %s\n", hex_lm_key);
					TALLOC_FREE(hex_lm_key);
				}

				if (ntlm_server_1_user_session_key 
				    && (memcmp(zeros, user_session_key, 
					       sizeof(user_session_key)) != 0)) {
					hex_user_session_key = hex_encode(NULL,
									  (const unsigned char *)user_session_key, 
									  sizeof(user_session_key));
					x_fprintf(x_stdout, "User-Session-Key: %s\n", hex_user_session_key);
					TALLOC_FREE(hex_user_session_key);
				}
			}
		}
		/* clear out the state */
		challenge = data_blob(NULL, 0);
		nt_response = data_blob(NULL, 0);
		lm_response = data_blob(NULL, 0);
		SAFE_FREE(full_username);
		SAFE_FREE(username);
		SAFE_FREE(domain);
		SAFE_FREE(plaintext_password);
		ntlm_server_1_user_session_key = False;
		ntlm_server_1_lm_session_key = False;
		x_fprintf(x_stdout, ".\n");

		return;
	}

	request = buf;

	/* Indicates a base64 encoded structure */
	parameter = strstr_m(request, ":: ");
	if (!parameter) {
		parameter = strstr_m(request, ": ");
		
		if (!parameter) {
			DEBUG(0, ("Parameter not found!\n"));
			x_fprintf(x_stdout, "Error: Parameter not found!\n.\n");
			return;
		}
		
		parameter[0] ='\0';
		parameter++;
		parameter[0] ='\0';
		parameter++;

	} else {
		parameter[0] ='\0';
		parameter++;
		parameter[0] ='\0';
		parameter++;
		parameter[0] ='\0';
		parameter++;

		base64_decode_inplace(parameter);
	}

	if (strequal(request, "LANMAN-Challenge")) {
		challenge = strhex_to_data_blob(NULL, parameter);
		if (challenge.length != 8) {
			x_fprintf(x_stdout, "Error: hex decode of %s failed! (got %d bytes, expected 8)\n.\n", 
				  parameter,
				  (int)challenge.length);
			challenge = data_blob(NULL, 0);
		}
	} else if (strequal(request, "NT-Response")) {
		nt_response = strhex_to_data_blob(NULL, parameter);
		if (nt_response.length < 24) {
			x_fprintf(x_stdout, "Error: hex decode of %s failed! (only got %d bytes, needed at least 24)\n.\n", 
				  parameter,
				  (int)nt_response.length);
			nt_response = data_blob(NULL, 0);
		}
	} else if (strequal(request, "LANMAN-Response")) {
		lm_response = strhex_to_data_blob(NULL, parameter);
		if (lm_response.length != 24) {
			x_fprintf(x_stdout, "Error: hex decode of %s failed! (got %d bytes, expected 24)\n.\n", 
				  parameter,
				  (int)lm_response.length);
			lm_response = data_blob(NULL, 0);
		}
	} else if (strequal(request, "Password")) {
		plaintext_password = smb_xstrdup(parameter);
	} else if (strequal(request, "NT-Domain")) {
		domain = smb_xstrdup(parameter);
	} else if (strequal(request, "Username")) {
		username = smb_xstrdup(parameter);
	} else if (strequal(request, "Full-Username")) {
		full_username = smb_xstrdup(parameter);
	} else if (strequal(request, "Request-User-Session-Key")) {
		ntlm_server_1_user_session_key = strequal(parameter, "Yes");
	} else if (strequal(request, "Request-LanMan-Session-Key")) {
		ntlm_server_1_lm_session_key = strequal(parameter, "Yes");
	} else {
		x_fprintf(x_stdout, "Error: Unknown request %s\n.\n", request);
	}
}
static int do_global_checks(void)
{
	int ret = 0;
	SMB_STRUCT_STAT st;
	const char *socket_options;

	if (lp_security() >= SEC_DOMAIN && !lp_encrypt_passwords()) {
		fprintf(stderr, "ERROR: in 'security=domain' mode the "
				"'encrypt passwords' parameter must always be "
				"set to 'true'.\n\n");
		ret = 1;
	}

	if (lp_we_are_a_wins_server() && lp_wins_server_list()) {
		fprintf(stderr, "ERROR: both 'wins support = true' and "
				"'wins server = <server list>' cannot be set in "
				"the smb.conf file. nmbd will abort with this "
				"setting.\n\n");
		ret = 1;
	}

	if (strequal(lp_workgroup(), lp_netbios_name())) {
		fprintf(stderr, "WARNING: 'workgroup' and 'netbios name' "
				"must differ.\n\n");
	}

	if (!directory_exist_stat(lp_lock_directory(), &st)) {
		fprintf(stderr, "ERROR: lock directory %s does not exist\n\n",
		       lp_lock_directory());
		ret = 1;
	} else if ((st.st_ex_mode & 0777) != 0755) {
		fprintf(stderr, "WARNING: lock directory %s should have "
				"permissions 0755 for browsing to work\n\n",
		       lp_lock_directory());
	}

	if (!directory_exist_stat(lp_state_directory(), &st)) {
		fprintf(stderr, "ERROR: state directory %s does not exist\n\n",
		       lp_state_directory());
		ret = 1;
	} else if ((st.st_ex_mode & 0777) != 0755) {
		fprintf(stderr, "WARNING: state directory %s should have "
				"permissions 0755 for browsing to work\n\n",
		       lp_state_directory());
	}

	if (!directory_exist_stat(lp_cache_directory(), &st)) {
		fprintf(stderr, "ERROR: cache directory %s does not exist\n\n",
		       lp_cache_directory());
		ret = 1;
	} else if ((st.st_ex_mode & 0777) != 0755) {
		fprintf(stderr, "WARNING: cache directory %s should have "
				"permissions 0755 for browsing to work\n\n",
		       lp_cache_directory());
	}

	if (!directory_exist_stat(lp_pid_directory(), &st)) {
		fprintf(stderr, "ERROR: pid directory %s does not exist\n\n",
		       lp_pid_directory());
		ret = 1;
	}

	if (lp_passdb_expand_explicit()) {
		fprintf(stderr, "WARNING: passdb expand explicit = yes is "
				"deprecated\n\n");
	}

	/*
	 * Socket options.
	 */
	socket_options = lp_socket_options();
	if (socket_options != NULL &&
	    (strstr(socket_options, "SO_SNDBUF") ||
	     strstr(socket_options, "SO_RCVBUF") ||
	     strstr(socket_options, "SO_SNDLOWAT") ||
	     strstr(socket_options, "SO_RCVLOWAT")))
	{
		fprintf(stderr,
			"WARNING: socket options = %s\n"
			"This warning is printed because you set one of the\n"
			"following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n"
			"SO_RCVLOWAT\n"
			"Modern server operating systems are tuned for\n"
			"high network performance in the majority of situations;\n"
			"when you set 'socket options' you are overriding those\n"
			"settings.\n"
			"Linux in particular has an auto-tuning mechanism for\n"
			"buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n"
			"disabled if you specify a socket buffer size. This can\n"
			"potentially cripple your TCP/IP stack.\n\n"
			"Getting the 'socket options' correct can make a big\n"
			"difference to your performance, but getting them wrong\n"
			"can degrade it by just as much. As with any other low\n"
			"level setting, if you must make changes to it, make\n "
			"small changes and test the effect before making any\n"
			"large changes.\n\n",
			socket_options);
	}

	/*
	 * Password server sanity checks.
	 */

	if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) {
		const char *sec_setting;
		if(lp_security() == SEC_DOMAIN)
			sec_setting = "domain";
		else if(lp_security() == SEC_ADS)
			sec_setting = "ads";
		else
			sec_setting = "";

		fprintf(stderr, "ERROR: The setting 'security=%s' requires the "
				"'password server' parameter be set to the "
				"default value * or a valid password server.\n\n",
				sec_setting );
		ret = 1;
	}

	if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) {
		const char *sec_setting;
		if(lp_security() == SEC_DOMAIN)
			sec_setting = "domain";
		else if(lp_security() == SEC_ADS)
			sec_setting = "ads";
		else
			sec_setting = "";

		fprintf(stderr, "WARNING: The setting 'security=%s' should NOT "
				"be combined with the 'password server' "
				"parameter.\n"
				"(by default Samba will discover the correct DC "
				"to contact automatically).\n\n",
				sec_setting );
	}

	/*
	 * Password chat sanity checks.
	 */

	if(lp_security() == SEC_USER && lp_unix_password_sync()) {

		/*
		 * Check that we have a valid lp_passwd_program() if not using pam.
		 */

#ifdef WITH_PAM
		if (!lp_pam_password_change()) {
#endif

			if((lp_passwd_program(talloc_tos()) == NULL) ||
			   (strlen(lp_passwd_program(talloc_tos())) == 0))
			{
				fprintf(stderr,
					"ERROR: the 'unix password sync' "
					"parameter is set and there is no valid "
					"'passwd program' parameter.\n\n");
				ret = 1;
			} else {
				const char *passwd_prog;
				char *truncated_prog = NULL;
				const char *p;

				passwd_prog = lp_passwd_program(talloc_tos());
				p = passwd_prog;
				next_token_talloc(talloc_tos(),
						&p,
						&truncated_prog, NULL);
				if (truncated_prog && access(truncated_prog, F_OK) == -1) {
					fprintf(stderr,
						"ERROR: the 'unix password sync' "
						"parameter is set and the "
						"'passwd program' (%s) cannot be "
						"executed (error was %s).\n\n",
						truncated_prog,
						strerror(errno));
					ret = 1;
				}
			}

#ifdef WITH_PAM
		}
#endif

		if(lp_passwd_chat(talloc_tos()) == NULL) {
			fprintf(stderr,
				"ERROR: the 'unix password sync' parameter is "
				"set and there is no valid 'passwd chat' "
				"parameter.\n\n");
			ret = 1;
		}

		if ((lp_passwd_program(talloc_tos()) != NULL) &&
		    (strlen(lp_passwd_program(talloc_tos())) > 0))
		{
			/* check if there's a %u parameter present */
			if(strstr_m(lp_passwd_program(talloc_tos()), "%u") == NULL) {
				fprintf(stderr,
					"ERROR: the 'passwd program' (%s) "
					"requires a '%%u' parameter.\n\n",
					lp_passwd_program(talloc_tos()));
				ret = 1;
			}
		}

		/*
		 * Check that we have a valid script and that it hasn't
		 * been written to expect the old password.
		 */

		if(lp_encrypt_passwords()) {
			if(strstr_m( lp_passwd_chat(talloc_tos()), "%o")!=NULL) {
				fprintf(stderr,
					"ERROR: the 'passwd chat' script [%s] "
					"expects to use the old plaintext "
					"password via the %%o substitution. With "
					"encrypted passwords this is not "
					"possible.\n\n",
					lp_passwd_chat(talloc_tos()) );
				ret = 1;
			}
		}
	}

	if (strlen(lp_winbind_separator()) != 1) {
		fprintf(stderr, "ERROR: the 'winbind separator' parameter must "
				"be a single character.\n\n");
		ret = 1;
	}

	if (*lp_winbind_separator() == '+') {
		fprintf(stderr, "'winbind separator = +' might cause problems "
				"with group membership.\n\n");
	}

	if (lp_algorithmic_rid_base() < BASE_RID) {
		/* Try to prevent admin foot-shooting, we can't put algorithmic
		   rids below 1000, that's the 'well known RIDs' on NT */
		fprintf(stderr, "'algorithmic rid base' must be equal to or "
				"above %lu\n\n", BASE_RID);
	}

	if (lp_algorithmic_rid_base() & 1) {
		fprintf(stderr, "'algorithmic rid base' must be even.\n\n");
	}

#ifndef HAVE_DLOPEN
	if (lp_preload_modules()) {
		fprintf(stderr, "WARNING: 'preload modules = ' set while loading "
				"plugins not supported.\n\n");
	}
#endif

	if (!lp_passdb_backend()) {
		fprintf(stderr, "ERROR: passdb backend must have a value or be "
				"left out\n\n");
	}
	
	if (lp_os_level() > 255) {
		fprintf(stderr, "WARNING: Maximum value for 'os level' is "
				"255!\n\n");
	}

	if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) {
		fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n");
		ret = 1;
	}

	return ret;
}