Example #1
0
/* string_match - match string s against token tok */
static bool string_match(const char *tok,const char *s)
{
	size_t     tok_len;
	size_t     str_len;
	const char   *cut;

	/* Return true if a token has the magic value "ALL". Return
	 * true if the token is "FAIL". If the token starts with a "."
	 * (domain name), return true if it matches the last fields of
	 * the string. If the token has the magic value "LOCAL",
	 * return true if the string does not contain a "."
	 * character. If the token ends on a "." (network number),
	 * return true if it matches the first fields of the
	 * string. If the token begins with a "@" (netgroup name),
	 * return true if the string is a (host) member of the
	 * netgroup. Return true if the token fully matches the
	 * string. If the token is a netnumber/netmask pair, return
	 * true if the address is a member of the specified subnet.
	 */

	if (tok[0] == '.') {			/* domain: match last fields */
		if ((str_len = strlen(s)) > (tok_len = strlen(tok))
		    && strequal(tok, s + str_len - tok_len)) {
			return true;
		}
	} else if (tok[0] == '@') { /* netgroup: look it up */
#ifdef	HAVE_NETGROUP
		DATA_BLOB tmp;
		char *mydomain = NULL;
		char *hostname = NULL;
		bool netgroup_ok = false;

		if (memcache_lookup(
			    NULL, SINGLETON_CACHE,
			    data_blob_string_const_null("yp_default_domain"),
			    &tmp)) {

			SMB_ASSERT(tmp.length > 0);
			mydomain = (tmp.data[0] == '\0')
				? NULL : (char *)tmp.data;
		}
		else {
			yp_get_default_domain(&mydomain);

			memcache_add(
				NULL, SINGLETON_CACHE,
				data_blob_string_const_null("yp_default_domain"),
				data_blob_string_const_null(mydomain?mydomain:""));
		}

		if (!mydomain) {
			DEBUG(0,("Unable to get default yp domain. "
				"Try without it.\n"));
		}
		if (!(hostname = SMB_STRDUP(s))) {
			DEBUG(1,("out of memory for strdup!\n"));
			return false;
		}

		netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain);

		DEBUG(5,("looking for %s of domain %s in netgroup %s gave %s\n",
			 hostname,
			 mydomain?mydomain:"(ANY)",
			 tok+1,
			 BOOLSTR(netgroup_ok)));

		SAFE_FREE(hostname);

		if (netgroup_ok)
			return true;
#else
		DEBUG(0,("access: netgroup support is not configured\n"));
		return false;
#endif
	} else if (strequal(tok, "ALL")) {	/* all: match any */
		return true;
	} else if (strequal(tok, "FAIL")) {	/* fail: match any */
		return true;
	} else if (strequal(tok, "LOCAL")) {	/* local: no dots */
		if (strchr_m(s, '.') == 0 && !strequal(s, "unknown")) {
			return true;
		}
	} else if (strequal(tok, s)) {   /* match host name or address */
		return true;
	} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {	/* network */
		if (strncmp(tok, s, tok_len) == 0) {
			return true;
		}
	} else if ((cut = strchr_m(tok, '/')) != 0) {	/* netnumber/netmask */
		if ((isdigit(s[0]) && strchr_m(tok, '.') != NULL) ||
			(tok[0] == '[' && cut > tok && cut[-1] == ']') ||
			((isxdigit(s[0]) || s[0] == ':') &&
				strchr_m(tok, ':') != NULL)) {
			/* IPv4/netmask or
			 * [IPv6:addr]/netmask or IPv6:addr/netmask */
			return masked_match(tok, cut, s);
		}
	} else if (strchr_m(tok, '*') != 0 || strchr_m(tok, '?')) {
		return unix_wild_match(tok, s);
	}
	return false;
}
Example #2
0
BOOL create_next_pdu(pipes_struct *p)
{
	RPC_HDR_RESP hdr_resp;
	BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
	BOOL auth_seal   = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0);
	uint32 ss_padding_len = 0;
	uint32 data_len;
	uint32 data_space_available;
	uint32 data_len_left;
	prs_struct outgoing_pdu;
	uint32 data_pos;

	/*
	 * If we're in the fault state, keep returning fault PDU's until
	 * the pipe gets closed. JRA.
	 */

	if(p->fault_state) {
		setup_fault_pdu(p, NT_STATUS(0x1c010002));
		return True;
	}

	memset((char *)&hdr_resp, '\0', sizeof(hdr_resp));

	/* Change the incoming request header to a response. */
	p->hdr.pkt_type = RPC_RESPONSE;

	/* Set up rpc header flags. */
	if (p->out_data.data_sent_length == 0) {
		p->hdr.flags = RPC_FLG_FIRST;
	} else {
		p->hdr.flags = 0;
	}

	/*
	 * Work out how much we can fit in a single PDU.
	 */

	data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
	if(p->ntlmssp_auth_validated) {
		data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN);
	} else if(p->netsec_auth_validated) {
		data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN);
	}

	/*
	 * The amount we send is the minimum of the available
	 * space and the amount left to send.
	 */

	data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length;

	/*
	 * Ensure there really is data left to send.
	 */

	if(!data_len_left) {
		DEBUG(0,("create_next_pdu: no data left to send !\n"));
		return False;
	}

	data_len = MIN(data_len_left, data_space_available);

	/*
	 * Set up the alloc hint. This should be the data left to
	 * send.
	 */

	hdr_resp.alloc_hint = data_len_left;

	/*
	 * Work out if this PDU will be the last.
	 */

	if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) {
		p->hdr.flags |= RPC_FLG_LAST;
		if ((auth_seal || auth_verify) && (data_len_left % 8)) {
			ss_padding_len = 8 - (data_len_left % 8);
			DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n",
				ss_padding_len ));
		}
	}

	/*
	 * Set up the header lengths.
	 */

	if (p->ntlmssp_auth_validated) {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
			data_len + ss_padding_len +
			RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN;
		p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN;
	} else if (p->netsec_auth_validated) {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
			data_len + ss_padding_len +
			RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
		p->hdr.auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
	} else {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len;
		p->hdr.auth_len = 0;
	}

	/*
	 * Init the parse struct to point at the outgoing
	 * data.
	 */

	prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
	prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);

	/* Store the header in the data stream. */
	if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) {
		DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR.\n"));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) {
		DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_RESP.\n"));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	/* Store the current offset. */
	data_pos = prs_offset(&outgoing_pdu);

	/* Copy the data into the PDU. */

	if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) {
		DEBUG(0,("create_next_pdu: failed to copy %u bytes of data.\n", (unsigned int)data_len));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	/* Copy the sign/seal padding data. */
	if (ss_padding_len) {
		char pad[8];
		memset(pad, '\0', 8);
		if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) {
			DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len));
			prs_mem_free(&outgoing_pdu);
			return False;
		}
	}

	if (p->ntlmssp_auth_validated) {
		/*
		 * NTLMSSP processing. Mutually exclusive with Schannel.
		 */
		uint32 crc32 = 0;
		char *data;

		DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n",
			 BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len));

		/*
		 * Set data to point to where we copied the data into.
		 */

		data = prs_data_p(&outgoing_pdu) + data_pos;

		if (auth_seal) {
			crc32 = crc32_calc_buffer(data, data_len + ss_padding_len);
			NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len);
		}

		if (auth_seal || auth_verify) {
			RPC_HDR_AUTH auth_info;

			init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE,
					auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL,
					(auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0));
			if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
				DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
				prs_mem_free(&outgoing_pdu);
				return False;
			}
		}

		if (auth_verify) {
			RPC_AUTH_NTLMSSP_CHK ntlmssp_chk;
			char *auth_data = prs_data_p(&outgoing_pdu);

			p->ntlmssp_seq_num++;
			init_rpc_auth_ntlmssp_chk(&ntlmssp_chk, NTLMSSP_SIGN_VERSION,
					crc32, p->ntlmssp_seq_num++);
			auth_data = prs_data_p(&outgoing_pdu) + prs_offset(&outgoing_pdu) + 4;
			if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, &outgoing_pdu, 0)) {
				DEBUG(0,("create_next_pdu: failed to marshall RPC_AUTH_NTLMSSP_CHK.\n"));
				prs_mem_free(&outgoing_pdu);
				return False;
			}
			NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4);
		}
	} else if (p->netsec_auth_validated) {
		/*
		 * Schannel processing. Mutually exclusive with NTLMSSP.
		 */
		int auth_type, auth_level;
		char *data;
		RPC_HDR_AUTH auth_info;

		RPC_AUTH_NETSEC_CHK verf;
		prs_struct rverf;
		prs_struct rauth;

		data = prs_data_p(&outgoing_pdu) + data_pos;
		/* Check it's the type of reply we were expecting to decode */

		get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level);
		init_rpc_hdr_auth(&auth_info, auth_type, auth_level, 
				  ss_padding_len, 1);

		if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
			DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
			prs_mem_free(&outgoing_pdu);
			return False;
		}

		prs_init(&rverf, 0, p->mem_ctx, MARSHALL);
		prs_init(&rauth, 0, p->mem_ctx, MARSHALL);

		netsec_encode(&p->netsec_auth, 
			      p->netsec_auth.auth_flags,
			      SENDER_IS_ACCEPTOR,
			      &verf, data, data_len + ss_padding_len);

		smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, 
			&verf, &outgoing_pdu, 0);

		p->netsec_auth.seq_num++;
	}

	/*
	 * Setup the counts for this PDU.
	 */

	p->out_data.data_sent_length += data_len;
	p->out_data.current_pdu_len = p->hdr.frag_len;
	p->out_data.current_pdu_sent = 0;

	prs_mem_free(&outgoing_pdu);
	return True;
}
Example #3
0
File: open.c Project: jophxy/samba
static BOOL open_file(files_struct *fsp,connection_struct *conn,
		      const char *fname1,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access)
{
	extern struct current_user current_user;
	pstring fname;
	int accmode = (flags & O_ACCMODE);
	int local_flags = flags;

	fsp->fd = -1;
	fsp->oplock_type = NO_OPLOCK;
	errno = EPERM;

	pstrcpy(fname,fname1);

	/* Check permissions */

	/*
	 * This code was changed after seeing a client open request 
	 * containing the open mode of (DENY_WRITE/read-only) with
	 * the 'create if not exist' bit set. The previous code
	 * would fail to open the file read only on a read-only share
	 * as it was checking the flags parameter  directly against O_RDONLY,
	 * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
	 * JRA.
	 */

	if (!CAN_WRITE(conn)) {
		/* It's a read-only share - fail if we wanted to write. */
		if(accmode != O_RDONLY) {
			DEBUG(3,("Permission denied opening %s\n",fname));
			check_for_pipe(fname);
			return False;
		} else if(flags & O_CREAT) {
			/* We don't want to write - but we must make sure that O_CREAT
			   doesn't create the file if we have write access into the
			   directory.
			*/
			flags &= ~O_CREAT;
		}
	}

	/*
	 * This little piece of insanity is inspired by the
	 * fact that an NT client can open a file for O_RDONLY,
	 * but set the create disposition to FILE_EXISTS_TRUNCATE.
	 * If the client *can* write to the file, then it expects to
	 * truncate the file, even though it is opening for readonly.
	 * Quicken uses this stupid trick in backup file creation...
	 * Thanks *greatly* to "David W. Chapman Jr." <*****@*****.**>
	 * for helping track this one down. It didn't bite us in 2.0.x
	 * as we always opened files read-write in that release. JRA.
	 */

	if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
		DEBUG(10,("open_file: truncate requested on read-only open for file %s\n",fname ));
		local_flags = (flags & ~O_ACCMODE)|O_RDWR;
	}

	/* actually do the open */

	if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
			(local_flags & O_CREAT) || ((local_flags & O_TRUNC) == O_TRUNC) ) {

		/*
		 * We can't actually truncate here as the file may be locked.
		 * open_file_shared will take care of the truncate later. JRA.
		 */

		local_flags &= ~O_TRUNC;

#if defined(O_NONBLOCK) && defined(S_ISFIFO)
		/*
		 * We would block on opening a FIFO with no one else on the
		 * other end. Do what we used to do and add O_NONBLOCK to the
		 * open flags. JRA.
		 */

		if (VALID_STAT(*psbuf) && S_ISFIFO(psbuf->st_mode))
			local_flags |= O_NONBLOCK;
#endif
		fsp->fd = fd_open(conn, fname, local_flags, mode);

		if (fsp->fd == -1)  {
			DEBUG(3,("Error opening file %s (%s) (local_flags=%d) (flags=%d)\n",
				 fname,strerror(errno),local_flags,flags));
			check_for_pipe(fname);
			return False;
		}
	} else
		fsp->fd = -1; /* What we used to call a stat open. */

	if (!VALID_STAT(*psbuf)) {
		int ret;

		if (fsp->fd == -1)
			ret = vfs_stat(conn, fname, psbuf);
		else {
			ret = vfs_fstat(fsp,fsp->fd,psbuf);
			/* If we have an fd, this stat should succeed. */
			if (ret == -1)
				DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) ));
		}

		/* For a non-io open, this stat failing means file not found. JRA */
		if (ret == -1) {
			fd_close(conn, fsp);
			return False;
		}
	}

	/*
	 * POSIX allows read-only opens of directories. We don't
	 * want to do this (we use a different code path for this)
	 * so catch a directory open and return an EISDIR. JRA.
	 */

	if(S_ISDIR(psbuf->st_mode)) {
		fd_close(conn, fsp);
		errno = EISDIR;
		return False;
	}

	fsp->mode = psbuf->st_mode;
	fsp->inode = psbuf->st_ino;
	fsp->dev = psbuf->st_dev;
	fsp->vuid = current_user.vuid;
	fsp->size = psbuf->st_size;
	fsp->pos = -1;
	fsp->can_lock = True;
	fsp->can_read = ((flags & O_WRONLY)==0);
	fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
	fsp->share_mode = 0;
	fsp->desired_access = desired_access;
	fsp->print_file = False;
	fsp->modified = False;
	fsp->oplock_type = NO_OPLOCK;
	fsp->sent_oplock_break = NO_BREAK_SENT;
	fsp->is_directory = False;
	fsp->directory_delete_on_close = False;
	fsp->conn = conn;
	/*
	 * Note that the file name here is the *untranslated* name
	 * ie. it is still in the DOS codepage sent from the client.
	 * All use of this filename will pass though the sys_xxxx
	 * functions which will do the dos_to_unix translation before
	 * mapping into a UNIX filename. JRA.
	 */
	string_set(&fsp->fsp_name,fname);
	fsp->wbmpx_ptr = NULL;      
	fsp->wcp = NULL; /* Write cache pointer. */

	DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
		 *current_user_info.smb_name ? current_user_info.smb_name : conn->user,fsp->fsp_name,
		 BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
		 conn->num_files_open + 1));

	return True;
}
Example #4
0
File: tmbd.c Project: cbh34680/tmb
static bool doMain_(const struct pgargs_t* pgargs, char** argv)
{
TMB_ENTER
	const char* const pidpath = TMB_DEFAULT_PIDPATH;
	const char* const logpath = TMB_DEFAULT_DAEMON_LOGPATH;

	FILE* logfp_ = NULL;

// 実行済 frameid キャッシュ
	int proced_idx = 0;
	int proced[PROCED_FRAMEID_CACHE + 1] = { 0 };
	proced[PROCED_FRAMEID_CACHE] = -1;

	struct rusage usage;
	const time_t boottime = time(NULL);

	struct tmb_schedule_t schedule = { 0 };
	char pgfullpath[PATH_MAX] = { 0 };

//
	openlog("tmbd", LOG_PID, LOG_USER);

// プログラムのフルパス

	if (! getPgFullpath_(pgfullpath, sizeof(pgfullpath)))
	{
		TMB_FIRE("fault: getPgFullpath_");
	}

// ログ出力先ファイル

	if (pgargs->foreground)
	{
		logfp_ = stderr;
	}
	else
	{
		logfp_ = fopen(logpath, "ae");
		if (! logfp_)
		{
			syslog(LOG_ERR, "'%s' logfile open error, errno=%d", logpath, errno);
			TMB_FIRE("error: fopen");
		}
	}

	syslog(LOG_INFO, "Starting ...");

	const bool auto_reboot = pgargs->auto_reboot && (! pgargs->foreground);

#ifdef TMB_DEBUG
	const char* const BuildMode_ = "debug";
#else
	const char* const BuildMode_ = "release";
#endif

	DLOG("New Process Start(%d) - build(%s)", getpid(), BuildMode_);
	DLOG("data-version=%d", tmb_format_version());
	DLOG("path=%s", pgfullpath);
	DLOG("auto-reboot=%s", BOOLSTR(auto_reboot));

	if (! initPidFile_())
	{
		TMB_FIRE("fault: initPidFile_");
	}

//
// 処理対象となるシグナルを設定
//
	sigset_t ss_wait;
	sigemptyset(&ss_wait);

	const int signals[] = { SIGALRM, SIGUSR1, SIGUSR2, SIGHUP, SIGTERM, SIGCHLD, SIGINT, };

	for (size_t i=0; i<(sizeof(signals) / sizeof(signals[0])); i++)
	{
		if (sigaddset(&ss_wait, signals[i]) == -1)
		{
			TMB_FIRE("error: sigaddset");
		}
	}

	if (sigprocmask(SIG_BLOCK, &ss_wait, NULL) == -1)
	{
		TMB_FIRE("error: sigprocmask");
	}

//
// シグナル待ちのループ処理を開始
//
	syslog(LOG_INFO, "Started.");
	DLOG("Started.");

	fflush(logfp_);

	bool reboot_condition = false;

	time_t waitstart = 0;
	bool from_timeout = false;
	int timeout_num = 0;
	time_t last_loadtime = 0;
	bool reload = true;

	int job_start = 0;
	int job_exit = 0;

	while (true)
	{
		const time_t lottime = time(NULL);

// 念のためバックトレースを初期化

		tmb_reset_backtrace();

		if (reload)
		{
			reload = false;

// スケジュールのリロード要求

			DLOG("reloading...");

			last_loadtime = lottime;

			if (! loadSchedule_(&schedule, lottime, logfp_))
			{
				TMB_FIRE("fault: loadSchedule_");
			}

			DLOG("reloaded, last(objectid=%d)", schedule.last_objectid);
			syslog(LOG_INFO, "reloaded, last(objectid=%d)", schedule.last_objectid);

			DLOG("list-num(once=%d rept=%d)", schedule.oncelist_num, schedule.reptlist_num);

			if (from_timeout)
			{
				DLOG("wait-time=%ld sec, timeout-num=%d",
					lottime - waitstart, timeout_num);

				waitstart = 0;
			}
		}

//
// 不足分の once タイマーを設定
//
// --> "pending signals" の数を超えるタイマーを登録できないため数を限定して設定
//
		if (! reSetOnceTimerWithLimit_(&schedule, ONCETIMER_CREATE_LIMIT, proced, lottime, logfp_))
		{
			TMB_FIRE("fault: reSetTimerWithLimit_");
		}

//
// シグナル待ち
//
// --> SIGHUP が連続するとタイマー処理が乱れるためポーリング処理に変更
//
		if (waitstart == 0)
		{
			waitstart = lottime;
			timeout_num = 0;

			DLOG("wait for signal...");
			fflush(logfp_);
		}

		int signo = -1;
		siginfo_t si_wait = { 0 };
		from_timeout = false;

// 0.5 秒
		//signo = sigtimedwait(&ss_wait, &si_wait, &(struct timespec){ .tv_nsec=500000000, });
// 1 秒
		signo = sigtimedwait(&ss_wait, &si_wait, &(struct timespec){ .tv_sec=1, });

		const time_t sigtime = time(NULL);
		const time_t uptime = sigtime - boottime;

		if (signo == -1)
		{
			if (errno != EAGAIN)
			{
				TMB_FIRE("error: sigwaitinfo");
			}
// タイムアウト
			from_timeout = true;
			timeout_num++;
		}
		else
		{
			DLOG("wait-time=%ld sec, timeout-num=%d", sigtime - waitstart, timeout_num);
			waitstart = 0;

// タイムアウト以外のときに情報を出力

			const long remaining = UPTIME_EXPIRES - (time(NULL) - boottime);

			DLOG("#")
			DLOG("# catch signal, signo=%d uptime=%ld", signo, uptime);
			DLOG("# si_signo=%d si_code=%d si_pid=%d si_uid=%d si_int=%d",
				si_wait.si_signo, si_wait.si_code, si_wait.si_pid,
				si_wait.si_uid, si_wait.si_int);
			DLOG("# boottime=%ld until-reboot=%ld", boottime, remaining);
			DLOG("# any-uptime=%ld file-uppid=%d", schedule.any_uptime, schedule.file_uppid);
			DLOG("# any-updnum=%d", schedule.any_updnum);
			DLOG("# last-objectid=%d", schedule.last_objectid);
			DLOG("# job-start=%d job-exit=%d", job_start, job_exit);

			if (getrusage(RUSAGE_SELF, &usage) == 0)
			{
				DLOG("# utime=%ld stime=%ld maxrss=%ld",
					usage.ru_utime.tv_sec, usage.ru_stime.tv_sec, usage.ru_maxrss);

				DLOG("# minflt=%ld majflt=%ld nvcsw=%ld",
					usage.ru_minflt, usage.ru_majflt, usage.ru_nvcsw);
			}
			DLOG("#")

		}

// シグナルごとの処理

		switch (signo)
		{
			case SIGINT:
			case SIGTERM:
			{
// "tmbd -k"
				DLOG("(SIGTERM/SIGINT) Exiting...");
				syslog(LOG_INFO, "Exiting...");

// プロセスの終了
				TMB_RETURN();

				break;
			}

			case SIGUSR1:
			{
// "tmbd -o"
				DLOG("(SIGUSR1) re-open log file");

// ログファイルを開きなおす
				if (! pgargs->foreground)
				{
					fflush(logfp_);

					logfp_ = freopen(logpath, "ae", logfp_);
					if (! logfp_)
					{
						syslog(LOG_ERR, "'%s' logfile open error, errno=%d",
							logpath, errno);

						TMB_FIRE("error: freopen");
					}

					DLOG("Restart Logging.");
				}

				break;
			}

			case SIGUSR2:
			{
				DLOG("(SIGUSR2) si_int=%d", si_wait.si_int);

				switch (si_wait.si_int)
				{
					case SIGUSR2_DUMP:
					{
// "tmbd -p"
						const char* const dmppath = TMB_DEFAULT_DUMPPATH;
						DLOG("dump Schedule to '%s'", dmppath);

						FILE* fp = fopen(dmppath, "w");
						if (! dmppath)
						{
							DLOG("error: open file(w)");

							break;
						}

						if (! tmb_dump(&schedule, fp))
						{
							DLOG("fault: tmb_dmp");
						}

						fclose(fp);
						fp = NULL;

						break;
					}

					case SIGUSR2_REBOOT:
					{
// "tmbd -R"
						DLOG("reboot process");

						if (! pgargs->foreground)
						{
							reboot_condition = true;
						}

						break;
					}

					default:
					{
						DLOG("illegal si_int (%d)", si_wait.si_int);

						break;
					}
				}

				break;
			}

			case SIGHUP:
			{
// "tmbd -r"
				DLOG("(SIGHUP) Reload config...");

				break;
			}

			case SIGALRM:
			{
// フレームを処理
				const int frameid = si_wait.si_value.sival_int;

				DLOG("(SIGALRM) frameid=%d", frameid);

				pid_t pid = onTimer_(&schedule, frameid, proced, sigtime, logfp_);

				if (pid == (pid_t)-1)
				{
					TMB_FIRE("fault: onTimer_");
				}

				if (pid)
				{
					DLOG("child-process started (pid=%d)", pid);

// 処理済のフレームを登録
					proced[proced_idx++] = frameid;

					if (proced[proced_idx] == -1)
					{
						proced_idx = 0;
					}

					job_start++;
				}
				else
				{
// 重複フレーム
					DLOG("warn: duplicate-entry frameid=%d", frameid);
				}

				break;
			}

			case SIGCHLD:
			{
				DLOG("(SIGCHLD) wait child-process...");

				int waited = handle_SIGCHLD_(logfp_);

				if (waited == -1)
				{
					TMB_FIRE("fault: handle_SIGCHLD_");
				}


				DLOG("child-process ended (num=%d)", waited);

				job_exit += waited;

				break;
			}
		}

		// --------------------------------------------------------------------------------------

		if (auto_reboot && ! reboot_condition)
		{
// 24 時間以上稼動したか
			if (uptime > UPTIME_EXPIRES)
			{
// 再起動条件を ON
				DLOG("set reboot-condition=on");
				reboot_condition = true;
			}
		}

// 再起動条件に合致するか

		if (reboot_condition)
		{
			DLOG("check rebootable...");

// 実行中のプロセスが存在しないか

			if ((job_start - job_exit) == 0)
			{
// 数秒以内に実行予定のフレームが存在するか

				if (isReserved_(&schedule, sigtime, TMB_DEFAULT_REBOOT_MARGIN))
				{
					DLOG("can not reboot (reserved)");
				}
				else
				{
// 再起動の実行
					DLOG("start reboot process...");

					if (createRebootProcess_(pgfullpath, argv, &schedule))
					{
						DLOG("success, Exiting...");
						syslog(LOG_INFO, "Exiting...");

						TMB_RETURN();

						break;
					}

					DLOG("fault: createRebootProcess_");
				}
			}
			else
			{
				DLOG("can not reboot (job running)");
			}
		}

// スケジュールが更新されたかチェック

		const char* const datpath = TMB_DEFAULT_DATAPATH;

		struct stat sb = { 0 };
		if (lstat(datpath, &sb) == 0)
		{
			if (sb.st_mtim.tv_sec >= sigtime)
			{
// 連続した書き込みが終わるまで待つ

				DLOG("wait until update end");
			}
			else if (sb.st_mtim.tv_sec >= last_loadtime)
			{
				DLOG("data updated, check reloadable?");
				DLOG("file=%ld mem=%ld", sb.st_mtim.tv_sec, last_loadtime);

// 数秒以内に実行予定のフレームが存在するか

				if (isReserved_(&schedule, sigtime, TMB_DEFAULT_RELOAD_MARGIN))
				{
					DLOG("can not reload (reserved)");
				}
				else
				{
// スケジュールのリロード
					reload = true;

					DLOG("ok reloadable");
				}
			}
		}

#ifdef TMB_DEBUG
		fflush(logfp_);
#endif
	}
Example #5
0
static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata,
			  uint32 fragment_start, int len, int auth_len, uint8 pkt_type,
			  int *pauth_padding_len)
{
	
	/*
	 * The following is that length of the data we must sign or seal.
	 * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN
	 * preceeding the auth_data.
	 */

	int data_len = len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;

	/*
	 * The start of the data to sign/seal is just after the RPC headers.
	 */
	char *reply_data = prs_data_p(rdata) + fragment_start + RPC_HEADER_LEN + RPC_HDR_REQ_LEN;

	RPC_HDR_AUTH rhdr_auth; 

	char *dp = prs_data_p(rdata) + fragment_start + len -
		RPC_HDR_AUTH_LEN - auth_len;
	prs_struct auth_verf;

	*pauth_padding_len = 0;

	if (auth_len == 0) {
		if (cli->pipe_auth_flags == 0) {
			/* move along, nothing to see here */
			return True;
		}

		DEBUG(2, ("No authenticaton header recienved on reply, but this pipe is authenticated\n"));
		return False;
	}

	DEBUG(5,("rpc_auth_pipe: pkt_type: %d len: %d auth_len: %d NTLMSSP %s schannel %s sign %s seal %s \n",
		 pkt_type, len, auth_len, 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NETSEC), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SIGN), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SEAL)));

	if (dp - prs_data_p(rdata) > prs_data_size(rdata)) {
		DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n"));
		return False;
	}

	DEBUG(10,("rpc_auth_pipe: packet:\n"));
	dump_data(100, dp, auth_len);

	prs_init(&auth_verf, 0, cli->mem_ctx, UNMARSHALL);
	
	/* The endinness must be preserved. JRA. */
	prs_set_endian_data( &auth_verf, rdata->bigendian_data);
	
	/* Point this new parse struct at the auth section of the main 
	   parse struct - rather than copying it.  Avoids needing to
	   free it on every error
	*/
	prs_give_memory(&auth_verf, dp, RPC_HDR_AUTH_LEN + auth_len, False /* not dynamic */);
	prs_set_offset(&auth_verf, 0);

	{
		int auth_type;
		int auth_level;
		if (!smb_io_rpc_hdr_auth("auth_hdr", &rhdr_auth, &auth_verf, 0)) {
			DEBUG(0, ("rpc_auth_pipe: Could not parse auth header\n"));
			return False;
		}

		/* Let the caller know how much padding at the end of the data */
		*pauth_padding_len = rhdr_auth.padding;
		
		/* Check it's the type of reply we were expecting to decode */

		get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
		if (rhdr_auth.auth_type != auth_type) {
			DEBUG(0, ("BAD auth type %d (should be %d)\n",
				  rhdr_auth.auth_type, auth_type));
			return False;
		}
		
		if (rhdr_auth.auth_level != auth_level) {
			DEBUG(0, ("BAD auth level %d (should be %d)\n", 
				  rhdr_auth.auth_level, auth_level));
			return False;
		}
	}

	if (pkt_type == RPC_BINDACK) {
		if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
			/* copy the next auth_len bytes into a buffer for 
			   later use */

			DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len);
			BOOL store_ok;

			/* save the reply away, for use a little later */
			prs_copy_data_out((char *)ntlmssp_verf.data, &auth_verf, auth_len);

			store_ok = (NT_STATUS_IS_OK(ntlmssp_store_response(cli->ntlmssp_pipe_state, 
									   ntlmssp_verf)));

			data_blob_free(&ntlmssp_verf);
			return store_ok;
		} 
		else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
			/* nothing to do here - we don't seem to be able to 
			   validate the bindack based on VL's comments */
			return True;
		}
	}
	
	if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
		NTSTATUS nt_status;
		DATA_BLOB sig;
		if ((cli->pipe_auth_flags & AUTH_PIPE_SIGN) ||
		    (cli->pipe_auth_flags & AUTH_PIPE_SEAL)) {
			if (auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) {
				DEBUG(0,("rpc_auth_pipe: wrong ntlmssp auth len %d\n", auth_len));
				return False;
			}
			sig = data_blob(NULL, auth_len);
			prs_copy_data_out((char *)sig.data, &auth_verf, auth_len);
		}
	
		/*
		 * Unseal any sealed data in the PDU, not including the
		 * 8 byte auth_header or the auth_data.
		 */

		/*
		 * Now unseal and check the auth verifier in the auth_data at
		 * the end of the packet. 
		 */

		if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
			if (data_len < 0) {
				DEBUG(1, ("Can't unseal - data_len < 0!!\n"));
				return False;
			}
			nt_status = ntlmssp_unseal_packet(cli->ntlmssp_pipe_state, 
								 (unsigned char *)reply_data, data_len,
								 &sig);
		} 
		else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
			nt_status = ntlmssp_check_packet(cli->ntlmssp_pipe_state, 
								(const unsigned char *)reply_data, data_len,
								&sig);
		}

		data_blob_free(&sig);

		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(0, ("rpc_auth_pipe: could not validate "
				  "incoming NTLMSSP packet!\n"));
			return False;
		}
	}

	if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
		RPC_AUTH_NETSEC_CHK chk;

		if (auth_len != RPC_AUTH_NETSEC_CHK_LEN) {
			DEBUG(0,("rpc_auth_pipe: wrong schannel auth len %d\n", auth_len));
			return False;
		}

		if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign", 
						&chk, &auth_verf, 0)) {
			DEBUG(0, ("rpc_auth_pipe: schannel unmarshalling "
				  "RPC_AUTH_NETSECK_CHK failed\n"));
			return False;
		}

		if (!netsec_decode(&cli->auth_info,
				   cli->pipe_auth_flags,
				   SENDER_IS_ACCEPTOR,
				   &chk, reply_data, data_len)) {
			DEBUG(0, ("rpc_auth_pipe: Could not decode schannel\n"));
			return False;
		}

		cli->auth_info.seq_num++;

	}
	return True;
}
Example #6
0
// display extra information for a server
void dlgMain::OnServerListRightClick(wxListEvent& event)
{
    if (!m_LstCtrlServers->GetItemCount() || !m_LstCtrlServers->GetSelectedItemCount())
        return;
  
    wxInt32 i = m_LstCtrlServers->GetNextItem(-1, 
                                        wxLIST_NEXT_ALL, 
                                        wxLIST_STATE_SELECTED);
        
    wxListItem item;
    item.SetId(i);
    item.SetColumn(7);
    item.SetMask(wxLIST_MASK_TEXT);
        
    m_LstCtrlServers->GetItem(item);
        
    i = FindServer(item.GetText());

    static wxString text = _T("");
    
    text = wxString::Format(_T("Extra information:\n\n"
                              "Protocol version: %d\n"
                              "Email: %s\n"
                              "Website: %s\n\n"
                              "Timeleft: %d\n"
                              "Timelimit: %d\n"
                              "Fraglimit: %d\n\n"
                              "Item respawn: %s\n"
                              "Weapons stay: %s\n"
                              "Friendly fire: %s\n"
                              "Allow exiting: %s\n"
                              "Infinite ammo: %s\n"
                              "No monsters: %s\n"
                              "Monsters respawn: %s\n"
                              "Fast monsters: %s\n"
                              "Allow jumping: %s\n"
                              "Allow freelook: %s\n"
                              "WAD downloading: %s\n"
                              "Empty reset: %s\n"
                              "Clean maps: %s\n"
                              "Frag on exit: %s\n"
                              "Spectating: %s\n"
                              "Passworded: %s\n"),
                              QServer[i].info.version,
                              
                              QServer[i].info.emailaddr.c_str(),
                              QServer[i].info.webaddr.c_str(),
                              QServer[i].info.timeleft,
                              QServer[i].info.timelimit,
                              QServer[i].info.fraglimit,
                              
                              BOOLSTR(QServer[i].info.itemrespawn),
                              BOOLSTR(QServer[i].info.weaponstay),
                              BOOLSTR(QServer[i].info.friendlyfire),
                              BOOLSTR(QServer[i].info.allowexit),
                              BOOLSTR(QServer[i].info.infiniteammo),
                              BOOLSTR(QServer[i].info.nomonsters),
                              BOOLSTR(QServer[i].info.monstersrespawn),
                              BOOLSTR(QServer[i].info.fastmonsters),
                              BOOLSTR(QServer[i].info.allowjump),
                              BOOLSTR(QServer[i].info.sv_freelook),
                              BOOLSTR(QServer[i].info.waddownload),
                              BOOLSTR(QServer[i].info.emptyreset),
                              BOOLSTR(QServer[i].info.cleanmaps),
                              BOOLSTR(QServer[i].info.fragonexit),
                              BOOLSTR(QServer[i].info.spectating),
                              BOOLSTR(QServer[i].info.passworded));
    
    static wxTipWindow *tw = NULL;
                              
    if (tw)
	{
		tw->SetTipWindowPtr(NULL);
		tw->Close();
	}
	
	tw = NULL;

	if (!text.empty())
		tw = new wxTipWindow(m_LstCtrlServers, text, 120, &tw);
}
Example #7
0
/* string_match - match string against token */
static int string_match(char *tok,char *s)
{
    int     tok_len;
    int     str_len;
    char   *cut;

    /*
     * Return YES if a token has the magic value "ALL". Return FAIL if the
     * token is "FAIL". If the token starts with a "." (domain name), return
     * YES if it matches the last fields of the string. If the token has the
     * magic value "LOCAL", return YES if the string does not contain a "."
     * character. If the token ends on a "." (network number), return YES if
     * it matches the first fields of the string. If the token begins with a
     * "@" (netgroup name), return YES if the string is a (host) member of
     * the netgroup. Return YES if the token fully matches the string. If the
     * token is a netnumber/netmask pair, return YES if the address is a
     * member of the specified subnet.
     */

    if (tok[0] == '.') {			/* domain: match last fields */
	if ((str_len = strlen(s)) > (tok_len = strlen(tok))
	    && strcasecmp(tok, s + str_len - tok_len) == 0)
	    return (YES);
    } else if (tok[0] == '@') {			/* netgroup: look it up */
#ifdef	NETGROUP
      static char *mydomain = NULL;
      char *hostname = NULL;
      BOOL netgroup_ok = False;

      if (!mydomain) yp_get_default_domain(&mydomain);

      if (!mydomain) {
        DEBUG(0,("Unable to get default yp domain.\n"));
        return NO;
      }
      if (!(hostname = strdup(s))) {
	DEBUG(1,("out of memory for strdup!\n"));
	return NO;
      }

      netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain);

      DEBUG(5,("looking for %s of domain %s in netgroup %s gave %s\n", 
	       hostname,
	       mydomain, 
	       tok+1,
	       BOOLSTR(netgroup_ok)));

#ifdef NETGROUP_INSECURE
      /* if you really want netgroups that match non qualified names
	 then define NETGROUP_INSECURE. It can, however, be a big
	 security hole */
      {
	char        *clnt_domain;
	if (!netgroup_ok && (clnt_domain=strchr(hostname,'.'))) {
	  *clnt_domain++ = '\0';
	  netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain);
	}
      }
#endif

      free(hostname);
      
      if (netgroup_ok) return(YES);
#else
      DEBUG(0,("access: netgroup support is not configured\n"));
      return (NO);
#endif
    } else if (strcasecmp(tok, "ALL") == 0) {	/* all: match any */
	return (YES);
    } else if (strcasecmp(tok, "FAIL") == 0) {	/* fail: match any */
	return (FAIL);
    } else if (strcasecmp(tok, "LOCAL") == 0) {	/* local: no dots */
	if (strchr(s, '.') == 0 && strcasecmp(s, "unknown") != 0)
	    return (YES);
    } else if (!strcasecmp(tok, s)) {	/* match host name or address */
	return (YES);
    } else if (tok[(tok_len = strlen(tok)) - 1] == '.') {	/* network */
	if (strncmp(tok, s, tok_len) == 0)
	    return (YES);
    } else if ((cut = strchr(tok, '/')) != 0) {	/* netnumber/netmask */
	if (isdigit(s[0]) && masked_match(tok, cut, s))
	    return (YES);
    }
    return (NO);
}
Example #8
0
void parse_args(struct options *const opt, const int argc, const char *const argv[])
{
	struct argument_flags flags;
	int i;

	/* Set override flags */
	flags.program_name = basename((char *)argv[0]);
	flags.conf_file = DEFAULT_CONFIG_FILE;
	flags.quotes_file = NULL;
	flags.pid_file = NULL;
	flags.journal_file = NULL;
	flags.tproto = PROTOCOL_TNONE;
	flags.iproto = PROTOCOL_INONE;
	flags.daemonize = BOOLEAN_UNSET;
	flags.strict = true;

	/* Set default options, defined in options.h */
	opt->port = DEFAULT_PORT;
	opt->tproto = DEFAULT_TRANSPORT_PROTOCOL;
	opt->iproto = DEFAULT_INTERNET_PROTOCOL;
	opt->quotes_file = DEFAULT_QUOTES_FILE;
	opt->linediv = DEFAULT_LINE_DIVIDER;
	opt->pid_file = default_pidfile();
	opt->require_pidfile = DEFAULT_REQUIRE_PIDFILE;
	opt->daemonize = DEFAULT_DAEMONIZE;
	opt->drop_privileges = DEFAULT_DROP_PRIVILEGES;
	opt->is_daily = DEFAULT_IS_DAILY;
	opt->pad_quotes = DEFAULT_PAD_QUOTES;
	opt->allow_big = DEFAULT_ALLOW_BIG;
	opt->chdir_root = DEFAULT_CHDIR_ROOT;

	/* Parse arguments */
	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "--")) {
			break;
		} else if (!strncmp(argv[i], "--", 2)) {
			parse_long_option(argc, argv, &i, &flags);
		} else if (argv[i][0] == '-') {
			const char *next_arg = (i + 1 == argc) ? NULL : argv[i + 1];
			parse_short_options(argv[i] + 1, next_arg, &i, &flags);
		} else {
			printf("Unrecognized option: %s.\n", argv[i]);
			usage_and_exit(flags.program_name);
		}
	}

	/* Override config file options */
	opt->strict = flags.strict;

	if (flags.conf_file) {
		if (flags.conf_file[0] != '/') {
			opt->chdir_root = false;
		}

		parse_config(flags.conf_file, opt);
	}

	if (flags.pid_file) {
		opt->pid_file = strcmp(flags.pid_file, "none") ? flags.pid_file : NULL;
	}

	if (flags.quotes_file) {
		opt->quotes_file = flags.quotes_file;
	}

	if (flags.journal_file && !strcmp(flags.journal_file, "-")) {
		opt->journal_file = flags.journal_file;
	} else {
		opt->journal_file = NULL;
	}

	if (flags.iproto != PROTOCOL_INONE) {
		opt->iproto = flags.iproto;
	}

	if (flags.tproto != PROTOCOL_TNONE) {
		opt->tproto = flags.tproto;
	}

	if (flags.daemonize != BOOLEAN_UNSET) {
		opt->daemonize = flags.daemonize;
	}

#if DEBUG
	journal("\nContents of struct 'opt':\n");
	journal("opt = {\n");
	journal("	QuotesFile: %s\n",		BOOLSTR(opt->quotes_file));
	journal("	PidFile: %s\n",			opt->pid_file);
	journal("	Port: %u\n",			opt->port);
	journal("	QuoteDivider: %s\n",		name_option_quote_divider(opt->linediv));
	journal("	Protocol: %s\n",		name_option_protocol(opt->tproto, opt->iproto));
	journal("	Daemonize: %s\n",		BOOLSTR(opt->daemonize));
	journal("	RequirePidfile: %s\n",	  	BOOLSTR(opt->require_pidfile));
	journal("	DropPrivileges: %s\n",	  	BOOLSTR(opt->drop_privileges));
	journal("	DailyQuotes: %s\n",	  	BOOLSTR(opt->is_daily));
	journal("	AllowBigQuotes: %s\n",	  	BOOLSTR(opt->allow_big));
	journal("	ChdirRoot: %s\n",		BOOLSTR(opt->chdir_root));
	journal("}\n\n");
#endif /* DEBUG */
}