/* 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; }
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; }
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; }
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 }
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; }
// 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); }
/* 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); }
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 */ }